home *** CD-ROM | disk | FTP | other *** search
/ LSD Docs / LSD Docs.iso / FILEZ / lsd32.dms / lsd32.adf / AmigaGfx4.pp / AmigaGfx4
Text File  |  1990-09-07  |  198KB  |  5,089 lines

  1.  _________________________________________________________________________
  2. /#########################################################################\
  3. |#####...####..######..######......####...####..#####..##......##......###|
  4. |####.....###..######..########..#####.....###...####..##..######..#######|
  5. |###..###..##..######..########..####..###..##....###..##..######..#######|
  6. |###..###..##..######..########..####..###..##..#...#..##..######......###|
  7. |###.......##..######..########..####.......##..##.....##..######..#######|
  8. |###..###..##..######..########..####..###..##..###....##..######..#######|
  9. |###..###..##...#####...#######..####..###..##..####...##..######..#######|
  10. |###..###..##......##......##......##..###..##..#####..##......##......###|
  11. |#########################################################################|
  12. |####################################################################{RB}#|
  13. |=========================================================================|
  14. |                                      |
  15. |                   ----> PRESENTS <----                  |
  16. |                                      |
  17. |            AMIGA GRAPHICS INSIDE AND OUT - THE COMPLETE BOOK            |
  18. |                                      |
  19. |                > PART 4 <                  |
  20. |                                      |
  21. | Typed / Scanned / Edited By : RAZOR BLADE.                      |
  22. | Additional Typing by        : GLITCH ( + 8 pages by Asterix ! ).      |
  23. | Original Supplied by          : VIPER                      |
  24. |                                      |
  25. |-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-|
  26. |         CALL THE ALLIANCE WORLD HQ -> THE PLACE TO BE             |
  27. |       UNKNOWN PLEASURES --> +44 (0) 823 322 891 --> SYSOP: BARBARIAN    |
  28. |_________________________________________________________________________|
  29.  
  30.                      CHAPTER 7 - THE IFF-ILBM STANDARD
  31.                      =================================
  32.        
  33.        
  34. "IFF" is the abbreviation for "Interchange File Format. This format evolved
  35. from an agreement between two companies, Electronic Arts and Commodore when
  36. the Amiga was just being introduced. These companies decided that it would
  37. not be practical for users or programmers if each graphic program saved 
  38. graphics in a different format. If this happened then it is possible that
  39. Graphicraft or Aegis pictures would only work with Aegis software. Without
  40. a
  41. a standard format exchanging pictures between programs would be impossible.
  42. This is the reason why the standard format ILBM (InterLeave BitMap) was
  43. created. An ILBM file consists of many components. The following are the 
  44. most important:
  45.        
  46.            'BMHD' = BitMapHeaDer.
  47.        
  48. Identification: BMHDnnnn
  49.        
  50. Offset  Type     Description.
  51. ------- -------- -----------------------------------------------------
  52. +000    Word     Width of graphic.
  53. +002    Word     Height of graphic.
  54. +004    Word     X position this graphic.
  55. +006    Word     Y position this graphic.
  56. +008    Byte     Number of bitplanes (depth)
  57. +009    Byte     Masking
  58.                  0 = No Masking.
  59.                  1 = MAsking.
  60.                  2 = Transparent.
  61.                  3 = Lasso.
  62. +010    Byte     Data compression.
  63.                  0 = No Compression.
  64.                  1 = ByteRun1 algorithm.
  65. +011    Byte     Unused.
  66. +012    Word     "transparent" colour.
  67. +014    Byte     X aspect.
  68. +015    Byte     Y aspect.
  69. +016    Word     Width of Source Page.
  70. +018    Word     Height of Source Page.
  71.        
  72.                             PAGE 279
  73.        
  74. ---------------------------------------------------------------------------
  75.        
  76.        "CMAP" = ColorMap
  77.        
  78. Identification: CMAPnnnn
  79.        
  80. Offset  Type    Description
  81. ------- ------- ----------------------------------------------------------
  82. +001    Byte    Red (0-255)
  83. +002    Byte    Green (0-255)
  84. +003    Byte    Blue (0-255)
  85.        
  86.        
  87.        "BODY" = Bit-Planes.
  88.        
  89. Identification: BODYnnn
  90.        
  91. -----------------------------------------------------
  92. Bit-plane 1
  93. Bit-Plane 2
  94. (...)
  95. Bit-Plane n
  96. ------------------------------------------------------
  97.        
  98.     
  99.        "CAMG" = Amiga ViewPort Mode (Hires, lores, Lace, etc...)
  100.        
  101. Identificiation: CAMGnnnn
  102.        
  103. Offset  Type    Description
  104. ------- ------- ------------------------------------------------------
  105. +000    Long    ViewPort Mode (see chapter 4).
  106. ----------------------------------------------------------------------
  107.        
  108. Same as the color cycle information from GraphiCraft:
  109.        
  110.        "CCRT" - raphiCraft ColorCycle Data.
  111.        
  112. Identification: "CCRTnnnn"
  113.        
  114. Offset  Type    Description.
  115. ------- ------- ----------------------------------------------
  116. +000    Word    Direction.
  117.                 0 = Backwards.
  118.                 1 = Forwards.
  119. +002    Byte    Start (number of colour register; 0-31)
  120. +003    Byte    End (number of colour register; 0-31)
  121. +004    Long    Seconds.
  122. +008    Long    Micro Seconds.
  123. ---------------------------------------------------------------
  124.        
  125. These important data blocks represent the ILBM format file for every 
  126. graphic saved using this method.
  127.        
  128. The folowing program demonstrates how to load and display this type of 
  129. file. It is possible for you to load any ILBM graphic that you want. For 
  130. example, you can load a graphic that was created with your drawing program
  131. or an ILBM graphic from any other type of program.
  132.        
  133.                             PAGE 280
  134.      
  135. ---------------------------------------------------------------------------
  136.        
  137.        '####################################################
  138.        '#
  139.        '# Section: 7
  140.        '# Program: Load ILBM picture from disk.
  141.        '# Date   : 01/15/87
  142.        '# Author : TOB
  143.        '# Version: 1.0
  144.        '#
  145.        '# Loads pictures of any mode, including HAM, halfbrite and
  146.        '# any GraphiCraft Color Cycle.
  147.        '#
  148.        '# Based on ILBM IFF Interleaved Bitmap Standard published November
  149.        '# 15, 1985 in the Rom kenal manual.
  150.        '#
  151.        '#######################################################
  152.        
  153.        PRINT "Searching for .bmap files ........ "
  154.        
  155.        'DOS-library
  156.        DECLARE FUNCTION xOpen& LIBRARY
  157.        DECLARE FUNCTION xRead& LIBRARY
  158.        DECLARE FUNCTION Seek& LIBRARY
  159.        'xClose()
  160.        'Delay()
  161.        
  162.        'EXEC-library
  163.        DECLARE FUNCTION AllocMem& LIBRARY
  164.        DECLARE FUNCTION DoIO% LIBRARY
  165.        DECLARE FUNCTION OpenDevice% LIBRARY
  166.        DECLARE FUNCTION AllocSignal% LIBRARY
  167.        DECLARE FUNCTION FindTask& LIBRARY
  168.        'FreeMem()
  169.        
  170.        'GRAPHICS-library
  171.        DECLARE FUNCTION AllocRaster& LIBRARY
  172.        'SetRast()
  173.        'LoadRGB4()
  174.        
  175.        LIBRARY "dos.library"
  176.        LIBRARY "exec.library"
  177.        LIBRARY "graphics.library"
  178.        
  179.     main: '* LOAD
  180.        
  181.                             PAGE 281
  182.        
  183. ---------------------------------------------------------------------------
  184.        
  185.        CLS
  186.        PRINT "ILBM Loader"
  187.        PRINT
  188.        PRINT "Loads Standard IFF Graphic Files into"
  189.        PRINT "memory and displays the Picture."       
  190.        PRINT 
  191.        PRINT "The IFF Loader supports GraphiCraft color cycling,"
  192.        PRINT " the display of Hold-and-Modify (4096 colors)"
  193.        PRINT " and Halfbrite (64 colours)."
  194.        PRINT 
  195.        PRINT "In accordance with the ILBM standards it decodes packed"
  196.        PRINT "graphic files that use the ByteRun1 method and "
  197.        PRINT "displays them."
  198.        PRINT
  199.        PRINT "If desired, you can print the picture on a graphics"
  200.        PRINT " capable printer."
  201.        
  202.        LINE INPUT "Name of IBM File : ";ilbm.file$
  203.        LINE INPUT "Do you wantthe picture printed (Y/N) ? ";yn$
  204.        
  205.        LoadILBM ilbm.file$
  206.        ColorCycle -1
  207.        
  208.        IF yn$ = "y" THEN
  209.            WINDOW OUTPUT 2
  210.            Hardcopy
  211.        END IF
  212.        
  213.        WHILE INKEY$ = "":WEND
  214.        ILBMend
  215.        
  216.        LIBRARY CLOSE
  217.        
  218.     
  219.     Sub LoadILBM(ilbm.name$) STATIC
  220.        SHARED disk.handle&, buf.read&
  221.        SHARED buf.color&, but.rgb&
  222.        SHARED ilbm.error$, signal%
  223.        SHARED screen.kolor%, amiga.viewport&
  224.        SHARED ilbm.vp.mode&
  225.        SHARED amiga.rastport&
  226.        
  227.        disk.modeOldFile%  = 1005
  228.        disk.name$         = ilbm.name+CHR$(0)
  229.        
  230.        '* Open ILBM file
  231.        disk.handle& = xOpen&(SADD(disk.name%),1005)
  232.        IF disk.handle& = 0 THEN
  233.        
  234.                             PAGE 282
  235.        
  236. ---------------------------------------------------------------------------
  237.        
  238.            ilbm.error$ = "ILBM File "+ilbm.name$+" not on specified disk
  239.  and drawer. "
  240.            GOTO ilbm.error.A
  241.        END IF
  242.        
  243.        '* Setup disk read buffer.
  244.        mem.opt& = 2^0+2^16
  245.        buf.size& = 240
  246.        buf.add&  = AllocMem&(buf.size&,mem.opt&)
  247.        IF buf.add& = 0 THEN
  248.            ilbm.error$ = "Not enough buffer memory free."
  249.            GOTO ilbm.error.A
  250.        END IF
  251.        
  252.        '* Section buffer for chunk areas.
  253.        buf.read& = buf.add&+0*120
  254.        buf.rgb&  = buf.add&+1*120
  255.        
  256.        '* Is it an ILBM file ???
  257.        disk.wasread& = xRead&(disk.handle&,buf.read&,12)
  258.        ilbm.ID.$ = ""
  259.        FOR loop1% = 8 TO 11
  260.            ilbm.ID.$ = ilbm.ID.$ + CHR$(PEEK,buf.read&+loop1%))
  261.        NEXT loop1%
  262.        
  263.        IF ilbm.ID.$ <> "ILBM" THEN
  264.            ilbm.error$ = "File ":+ilbm.name$+" is not an ILBM file."
  265.            GOTO ilbm.error.A
  266.        END IF
  267.        
  268.        '* read data chunks from ILBM 
  269.        WHILE (signal%<>1) AND (ilbm.error$ = "")
  270.            ReadChunk
  271.        WEND
  272.        
  273.        '* Error ? 
  274.    ilbm.error.A:
  275.        IF ilbm.error$<>"" THEN
  276.            WINDOW CLOSE 2
  277.            SCREEN CLOSE 1
  278.            PRINT ilbm.error$
  279.            EXIT SUB
  280.        END IF
  281.        
  282.        '* All ok
  283.        CALL LoadRGB4(amiga.viewport&, buf.rgb&, screen.kolor%)
  284.        
  285.        '* Close ILBM file?
  286.        IF disk.handle & <> 0 THEN
  287.            CALL xClose(disk.handle&)
  288.        END IF
  289.        IF buf.add& <> 0 THEN
  290.            CALL FreeMem(buf.add&,buf.size&)
  291.        
  292.                             PAGE 283
  293.        
  294. ---------------------------------------------------------------------------
  295.        
  296.            buf.add& = 0
  297.        END IF
  298.        
  299.        '* Set ViewModes.
  300.         POKEW amiga.viewport&+32, ilbm.vp.mode&
  301.    END SUB
  302.        
  303.    SUB ILBMend STATIC
  304.        WINDOW CLOSE 2
  305.        SCREEN CLOSE 1
  306.    END SUB
  307.        
  308.    SUB ColorCycle(mode%) STATIC
  309.        SHARED ccrt.direction%
  310.        SHARED ccrt.start%, amiga.colortable&
  311.        SHARED ccrt.end%, screen.kolor%
  312.        SHARED ccrt.secs&, status%
  313.        SHARED ccrt.mics&, amiga.viewport&
  314.        
  315.        '* As intended.
  316.        IF (status% AND 2^4) <> 2^4 THEN
  317.            EXIT SUB
  318.        END IF
  319.        
  320.        '* Setup varaible field
  321.        DIM kolor.original%(screen.kolor%-1)
  322.        DIM kolor.actual%(screen.kolor%-1)
  323.        
  324.        '* all OK, save old color from ViewPort.
  325.        FOR loop1% = 0 TO screen.kolor%-1
  326.            kolor.original%(loop1%) = PEEKW(amiga.colortable&+2*loop1%)
  327.            kolor.actual%(loop1%) = kolor.original%(loop1%)
  328.        NEXT loop1%
  329.        
  330.        '* Colour cycling.
  331.        WHILE mode%<>0
  332.            '* Mode ?
  333.            IF mode% < 0 THEN
  334.                in$ = INKEY$
  335.                IF in$<>"" THEN mode% = 0
  336.            ELSE
  337.                mode% = mode% - 1
  338.            END IF
  339.            
  340.            '* Forwards ?
  341.            IF ccrt.direction% = 1 THEN
  342.                ccrt.backup% = kolor.actual%(ccrt.start%)
  343.                FOR loop1% = ccrt.start%+1 TO ccrt.end%
  344.                    kolor.actual%(loop1%-1)=kolor.actual%(loop1%)
  345.                NEXT loop1%
  346.                kolor.actual%(ccrt.end%) = ccrt.backup%
  347.        
  348.            '* Backwards.
  349.            ELSE
  350.        
  351.                             PAGE 284
  352.        
  353. ---------------------------------------------------------------------------
  354.        
  355.                ccrt.backup% = kolor.actual%(ccrt.end%)
  356.                FOR loop1% = ccrt.start%-1 TO ccrt.end% STEP -1
  357.                    kolor.actual%(loop1%+1) = kolor.actual%(loop1%)
  358.                NEXT loop1%
  359.                kolor.actual%(ccrt.start%) = ccrt.backup%
  360.            END IF
  361.            
  362.            CALL LoadRGB4(amiga.viewport&,VARPTR(kolor.actual%(0)),
  363.   screen.kolor%)
  364.            timeout& = 50*(ccrt.secs&+(ccrt.mics&/1000000&))
  365.            CALL Delay(timeout&)
  366.        WEND
  367.        
  368.        '* Restore original colors.
  369.        CALL LoadRGB4(amiga.viewport&,VARPTR(kolor.original%(0)),screen.kolor%)
  370.            
  371.        '* REturn fields.
  372.        ERASE kolor.original%
  373.        ERASE kolor.actual%
  374.   END SUB
  375.        
  376.    SUB ReadChunk STATIC
  377.        SHARED disk.handle&, buf.read&
  378.        SHARED buf.color&, buf.rgb&
  379.        SHARED ilbm.error$, signal%
  380.        SHARED screen.kolor%, amiga.viewport&
  381.        SHARED ilbm.vp.mode&, status%
  382.        SHARED amiga.rastport&
  383.        SHARED ccrt.direction%
  384.        SHARED ccrt.start%, amiga.colortable&
  385.        SHARED ccrt.end%, screen.kolor%
  386.        SHARED ccrt.secs&
  387.        SHARED ccrt.mics&
  388.        
  389.        '* Read chunk header.
  390.        disk.wasread& = xRead&(disk.handle&, buf.read&, 8)
  391.        ilbm.chunk& = PEEKL(buf.read&+4)
  392.        ilbm.ID.$ = ""
  393.        FOR loop1% = 0 TO 3
  394.            ilbm.ID.$ = ilbm.ID.$+CHR$(PEEK(buf.read&+loop1%))
  395.        NEXT loop1%
  396.        
  397.        '* The bitmap Header (BMHD) ? 
  398.        IF ilbm.ID.$ = "BMHD" THEN
  399.            '* Read chunk contents.
  400.            disk.wasread& = xRead&(disk.handle&,buf.read&,ilbm.chunk&)
  401.        
  402.            status% = status% OR 2^0
  403.            ilbm.width% = PEEKW(buf.read&+0)
  404.            ilbm.height% = PEEKW(buf.read&+2)
  405.            ilbm.depth% = PEEK(buf.read&+8)
  406.            ilbm.mode%  = PEEK(buf.read&+10)
  407.        
  408.                             PAGE 285
  409.        
  410. ---------------------------------------------------------------------------
  411.        
  412.            screen.width& = PEEKW(buf.read&+16)
  413.            screen.height% = PEEKW(buf.read&+18)
  414.            
  415.            '* Build Display Parameters.
  416.            ilbm.bytes% = ilbm.width%/8
  417.            screen.bytes% = screen.width%/8
  418.            screen.kolor% = 2^(ilbm.depth%)
  419.            
  420.            '* prepare for our display.
  421.        
  422.            '* Hires (Hi resolution ? )
  423.            IF screen.width%>320 THEN
  424.                screen.mode% = 2
  425.            ELSE
  426.                screen.mode% = 1
  427.            END IF
  428.            
  429.            '* Interlace (y = 0 - 399)
  430.            IF screen.height%>200 THEN screen.mode% = screen.mode%+2
  431.            
  432.            '* ILBM depth% = 6 -> HAM/Halfbrite ?
  433.            IF ilbm.depth% = 6 THEN 
  434.                ilbm.re% = -1
  435.            END IF
  436.            
  437.            depth% = ilbm.depth%+ilbm.reg%
  438.            SCREEN 1,screen.width%,screen.height%,depth%,screen.mode%
  439.            WINDOW 2,,,0,1
  440.            
  441.            '* System parameters
  442.            amiga.windo&          = WINDOW(7)
  443.            amiga.screen&         = PEEKL(amiga.windo&+46)
  444.            amiga.viewport&       = amiga.screen&+44
  445.            amiga.rastport&       = amiga.screen&+84
  446.            amiga.colormap&       = PEEKL(amiga.viewport&+4)
  447.            amiga.colortable&     = PEEKL(amiga.colormap&+4)
  448.            amiga.bitmap&         = PEEKL(amiga.rastport&+4)
  449.            FOR loop1% = 0 TO ilbm.depth%-1
  450.                amiga.plane&(loop1%) = PEEKL(amiga.bitmap&+8+loop1%*4)
  451.            NEXT loop1%
  452.            
  453.            '* For HAM/Halfbrite prepare 6 bitplanes.
  454.            IF ilbm.reg% = -1 THEN
  455.                ilbm.reg% = 0
  456.                newplane& = ALlocRaster&(screen.width%,screen.height%)
  457.                IF newplane& = 0 THEN
  458.                    ilbm.error$ = "Not enough memory free for 6 bitplanes!"
  459.                ELSE
  460.                    POKE amiga.bitmap&+5,6
  461.                    POKEL amiga.bitmap&+28,newplane&
  462.                END IF
  463.            
  464.                                PAGE 286
  465.        
  466. ---------------------------------------------------------------------------
  467.        
  468.            END IF
  469.            
  470.            ;* ColorTable (CMAP)?
  471.        ELSE IF ilbm.ID.$ = "CMAP" THEN
  472.            '* REad chunk contents.
  473.            disk.wasread& = xRead&(disk.handle&,buf.read&,ilbm.chunk&)
  474.            status = status% OR 2^1
  475.            
  476.            '* Calculate RGB table.
  477.            FOR loop1% = 0 TO screen.kolor% - 1
  478.                kolor.red% = PEEK(buf.read&+loop1%*3+0)
  479.                kolor.green%=PEEK(buf.read&+loop1%*3+1)
  480.                kolor.blue% =PEEK(buf.read&+loop1%*3+2)
  481.                kolor.rgb%  = kolor.green%+16*kolor.red%+1/16*kolor.blue%
  482.                POKEW buf.rgb&+2*loop1%,kolor.rgb%
  483.            NEXT loop1%
  484.        
  485.            '* Alignment.
  486.            IF (ilbm.chunk OR 1)=ilbm.chunk THEN
  487.                disk.wasread&=xRead&(disk.handle&,buf.read&,1)
  488.            END IF
  489.            
  490.            '* Viewport Mode (CAMG) AMIGA ? 
  491.        ELSE IF
  492.        ELSE IF ilbm.ID.$ = "CAMG" THEN
  493.            '* Read chunk contents.
  494.            disk.wasread& = xRead&(disk.handle&, buf.read&, ilbm.chunk&)
  495.            
  496.            status% = status% OR 2^4
  497.            ccrt.direction%   = PEEKW(buf.read&+0)
  498.            ccrt.start%       = PEEK (buf.read&+2)
  499.            ccrt.end%         = PEEK (buf.read&+3)
  500.            ccrt.secs&        = PEEKL (buf.read&+4)
  501.            ccrt.mics&        = PEEKL(buf.read&+8)
  502.            
  503.        '* Bitplanes (BODY) ?
  504.        ELSEIF ilbm.ID.$ = "BODY" THEN
  505.            status% = status% OR 2^2
  506.            
  507.            '* not compressed data.
  508.            IF ilbm.mode% = 0 THEN
  509.                FOR loop1% = 0 TO ilbm.height%-1
  510.                    FOR loop2% = 0 TO ilbm.depth%-1
  511.        
  512.                             PAGE 287
  513.        
  514. ---------------------------------------------------------------------------
  515.        
  516.                        screen.buffer& =amiga.plane&(loop2%)+(loop1%*
  517.   screen.bytes%)
  518.                        disk.wasread& = xRead&(disk.handle&,screen.buffer&,
  519.   ilbm.bytes%)
  520.                    NEXT loop2%
  521.                NEXT loop1%
  522.            
  523.            '* Compressed Data (ByteRun1-Encoding)
  524.            ELSEIF ilbm.mode% = 1 THEN
  525.                FOR loop1% = 0 TO ilbm.height%-1
  526.                    FOR loop2% = 0 TO ilbm.depth%-1
  527.                        screen.buffer& = amiga.plane&(loop2%)+(loop1%*
  528.  screen.bytes%)
  529.                        counter% = 0
  530.            
  531.                        '* Decoding.
  532.                        WHILE counter% <ilbm.bytes%
  533.                            disk.wasread& = xRead&(disk.handle&,buf.read&,1)
  534.                            code%  = PEEK(buf.read&)
  535.                            '* Code 1: read n bytes uncoded.
  536.                            IF code% < 128 THEN
  537.                               disk.wasread& = 
  538.   xRead&(disk.handle&,screen.buffer&+counter%,code%+1)
  539.                                counter% = counter%+code%+1
  540.                            '* Code 2 Repeat bytes (257-n) times.
  541.                            ELSEIF code% > 128 THEN
  542.                                disk.wasread& = xRead&(disk.handle&,buf.read&,1)
  543.                                disk.byte% = PEEK(buf.read%)
  544.                                FOR loop3% = counter% TO counter%+257-code%
  545.                                    POKE screen.buffer&+loop3%,disk.byte%
  546.                                NEXT loop3%
  547.                                counter% = counter%+257-code%
  548.                            '* Code 3 : no operation.
  549.                            ELSE 
  550.                                '* no operation.
  551.                            END IF
  552.                        WEND
  553.                    NEXT loop2%
  554.                NEXT loop1%
  555.            '* Different decoding method.
  556.            ELSE 
  557.                ilbm.error$ = "Data compression algorithm unknown. "
  558.            END IF
  559.        '* Process unimportant chunks. (GRAB, DEST, SPRT, etc...)
  560.        ELSE
  561.            ;* Read straigh count bytes.
  562.            IF (ilbm.chunk% OR 1)=ilbm.chunk% THEN
  563.                ilbm.chunk%=lib.chunk%+1
  564.            
  565.                             PAGE 288
  566.        
  567. ---------------------------------------------------------------------------
  568.        
  569.            END IF
  570.        
  571.        '*Move Disk cursor.
  572.        mode.current% = 0
  573.        stat& = Seek&(disk.handle&,ilbm.chunk%,0)
  574.        IF stat& = -1 THEN
  575.            ilbm.error = "DOS error. Seek() failed."
  576.        END IF
  577.        
  578.        END IF
  579.        
  580.        '* Error check.
  581.        IF disk.wasread& < - THEN
  582.            ilbm.error$ = "DOS Error. Read() Failed."
  583.        '* EOF (end of file) reached ?
  584.        ELSEIF disk.wasread& = 0 AND ((status% AND 7) <> 7 THEN
  585.            ilbm.error$ = "ILBM data chunks not present."
  586.            signal% = 1
  587.        ELSEIF (status% AND 7) = 7 THEN
  588.            signal% = 1
  589.        END IF
  590.    END SUB
  591.        
  592.        
  593.     SUB Hardcopy STATIC
  594.            mem.opt& = 2^0+2^16
  595.            p.io&    = AllocMem&(100,mem.opt&)
  596.            p.port&  = p.io&+62
  597.            IF p.io& = 0 THEN ERROR 7
  598.            
  599.            f.windo&        = WINDOW(7)
  600.            f.rastport&     = PEEKL(f.windo&+50)
  601.            f.width%        = PEEKW(f.windo&+112)
  602.            f.height%       = PEEKW(f.windo&+114)
  603.            f.screen&       = PEEKL(f.windo&+46)
  604.            f.viewport&     = f.screen&+44
  605.            f.colormap&     = PEEKL(f.viewport&+4)
  606.            f.vp.mode%      = PEEKW(f.viewport&+32)
  607.            
  608.            
  609.            p.sigBit% = AllocSignal%(-1)
  610.            IF p.sigBit% = -1 THEN
  611.                PRINT "No Signalbit free!"
  612.                CALL FreeMem(p.io&,100)
  613.                EXIT SUB
  614.            END IF
  615.            p.sigTask& = FindTask&(0)
  616.            
  617.            POKE p.port&+8,4
  618.            POKE p.port&+10,p.port&+34
  619.            POKE p.port&+15,p.sigBit%
  620.            POKEL p.port&+16,p.sigTask&
  621.            POKEL p.port&+20,p.port&+24
  622.        
  623.                                PAGE 289
  624.        
  625. ---------------------------------------------------------------------------
  626.        
  627.            POKEL p.port&+28,p.port&+20
  628.            POKE  p.port&+34,ASC("P")
  629.            POKE  p.port&+35,ASC("R")
  630.            POKE  p.port&+36,ASC("T")
  631.            
  632.            CALL AddPort(p.port&)
  633.            
  634.            POKE  p.io&+8,5
  635.            POKEL p.io&+14,p.port&
  636.            POKEW p.io&+28,11
  637.            POKEL p.io&+32,f.rastport&
  638.            POKEL p.io&+36,f.colormap&
  639.            POKEL p.io&+40,f.vp.mode%
  640.            POKEW p.io&+48,f.width%
  641.            POKEW p.io&+50,f.height%
  642.            POKEL p.io&+52,f.width%
  643.            POKEL p.io&+56,f.height%
  644.            POKEW p.io&+60,4
  645.        
  646.            d.name$ = "printer.device"+CHR$(0)
  647.            status% = OpenDevice%(SADD(d.name$),0,p.io&,0)
  648.            IF status% <> 0 THEN
  649.                PRINT "Printer is not free":
  650.                CALL FreeMem(p.io&,100)
  651.                CALL FreeSignal(p.sigBit%)
  652.                EXIT SUB
  653.            END IF
  654.            
  655.            ercond% = DoIO%(p.io&)
  656.            
  657.            CALL CloseDevice(p.io&)
  658.            CALL RemPort(p.port&)
  659.            CALL FreeMem(p.io&,100)
  660.            CALL FreeSignal(p.sigBit%)
  661.            PRINT "Error Code: ";ercond%
  662.        END SUB
  663.        
  664.        
  665. PROGRAM DESCRIPTION.
  666. ====================
  667.        
  668. The SUB program LoadILBM requires a string containing the name of the ILBM
  669. picture you want to load from disk. The picture must be in the active disk
  670. directory in order for the active program to find it (CHDIR directory). The
  671. Extras diskette for workbench 1.2 contains the Heart.ILBM file, which is 
  672. a good example picture to use. This program loads and displays the picture.
  673. Now you could call the SUB program ColorCycle. When this program finds a 
  674. CCRT ColorCycle data block, it activates the cycling, which creates a 
  675. motion like effect on the screen. This SUB program requires an integer 
  676. argument. If the argument is negative, the Amiga cycles the colours until 
  677. you press a key. If the argument is positive, the Amiga cycles the colors 
  678. for a time period determined by your argument. The SUB program ILBMend
  679. stops the display and closes both the screen and window.
  680.        
  681.                                PAGE 290
  682.        
  683. ------------------------------------------------------------------------
  684.        
  685. The DOS library routines are new in our program. You cannot use the built 
  686. in OPEN/INPUT#/CLOSE commands when working with ILBM files because these 
  687. commands place zeros in the data. Here is a short explanation of the DOS
  688. routines used:
  689.        
  690.        name$ = name$+CHR$(0)
  691.        disk.handle&=xOpen&(SADD(name$),1005)
  692.            
  693.         name$  : Name of file to be opened.
  694.         1005   : ModeOldFile - file already exists.
  695.         1006   : ModeNewFile - make file with this name.
  696.         dis.handle& = BPTR (pointer/4) in handler data block when 0, then
  697.                       xOpen failed.
  698.        
  699.        
  700.                         =================================
  701.        
  702.         wasread& = xRead(disk.handle&,buffer&,bytes&)
  703.        
  704.         disk.handle& : Address from xOpen call.
  705.         buffer&      : Address of a free memory area.
  706.         bytes&       : Number of bytes to be read from the actual disk
  707.                        cursor position that have to fit in the buffer!
  708.         wasread&     : Number of bytes read.
  709.                        =0: EOF (End Of File)
  710.                        smaller than zero: read error.
  711.        
  712.        
  713.                         ======================================
  714.        
  715.          oldpos& = Seek(disk.handle&,offset%,mode%)
  716.            
  717.          disk.handle&  : Address from xOpen call.
  718.          offset%       : Number of bytes to move the disk cursor.
  719.          mode%         : 0 = From current position.
  720.                         -1 = From file begin.
  721.                          1 = From file end.
  722.        
  723.        
  724.                          ======================================
  725.        
  726.          CALL xClose(disk.handle&)
  727.            
  728.          disk.handle& : Handle from xOpen command; closes file.
  729.          
  730.        
  731.                           =======================================
  732.        
  733.          CALL delay(ticks)
  734.            
  735.           tick  : 1/50/ second.
  736.           microseconds : 1/100000 second.
  737.        
  738. Waits for the specified time (however, this does not mean busy waiting, 
  739. the system has additional computing time free).
  740.        
  741.                             PAGE 291
  742.        
  743. ---------------------------------------------------------------------------
  744.        
  745. Special Features of the program:
  746. -------------------------------
  747.        
  748. This program not only supports the AmigaBASIC display modes hires and 
  749. interlace, but also the ILBM graphics in halfbrite (64 colors) and HAM mode
  750. (4096) colours. Both modes use six bitplanes. Whenever one of these modes 
  751. is encountered, a sixth bitplane is added to the screen. However, we do not
  752. clear this bitplane using FreeRaster. Instead, when the SCREEN CLOSE 
  753. statement closes the new screen, all the bitplanes, including the sixth
  754. bitplane that was added are automatically deleted.
  755.        
  756. The program is capable of decoding compacted bitplanes by using the 
  757. "ByteRun1" method. This method uses two control codes. When the first byte
  758. read is smaller than 128 then the following byte is simply loaded and used.
  759. When the first byte is a value greater than 128, the second byte is 
  760. repeated 257 times (normally signed bytes from -127 to +128 are used for a 
  761. more complicated compression algorithm). When the byte is equal to 128 
  762. nothing happens because it has a NOP (No Operation).
  763.        
  764.                             PAGE 292
  765.        
  766. ---------------------------------------------------------------------------
  767.  
  768.                 CHAPTER 8 - A 1024 * 1024 PAINT PROGRAM.
  769.        
  770. In the previous chapters you learned about the Amiga'a various system 
  771. components and how to program them. To conclude the BASIC portion of our 
  772. book, we have included a complete paint program that use superbitmap 
  773. layers.  The program also includes the capability of using the Amiga fonts,
  774. including their various modes and styles. Here is a brief description
  775. for the program and what it can do:
  776.        
  777.        * Full mouse and menu control.
  778.        * Up to 1024*1024 pixel sized drawings.
  779.        * Soft scrolling over the entire drawing area.
  780.        * Circles, lines, rectangles in the true rubberband technique.
  781.        * Freehand drawing.
  782.        * Text output in JAM1 and JAM2, complement and inverse.
  783.        * Up to 19 different fonts at the same time.
  784.        * Outline, italic, bold and underline text.
  785.        * Extensive Hardcopy functions.
  786.        * Printing of the entire 1024*1024 pixel graphic.
  787.        * Selected piece with enlargement/reduction.
  788.        * Distortion.
  789.        * Fill areas.
  790.        * Drawin grid.
  791.        * Block Erase.
  792.        * Copy a piece of the drawing.
  793.        * Self defined brushes and patterns.
  794.        
  795. Since the superbitmap planes are so large, this drawing program uses only
  796. one bitplane. Because of this our drawings are limited to black and white.
  797. We designed the program to create drawings that you can print. The large 
  798. drawing area makes it easy to create very detailed graphics that you can 
  799. then print on a graphics-capable printer in their original or a reduced
  800. size.
  801.        
  802.                             PAGE 293
  803.        
  804. -----------------------------------------------------------------------------
  805.        
  806.        '########################################
  807.        '# 
  808.        '# Section : 8
  809.        '# Program : Superbitmap Paint Program.
  810.        '# Date    : 04/16/87
  811.        '# Author  : tob
  812.        '# Version : 1.0
  813.        '#
  814.        '########################################
  815.        
  816.        PRINT "Searching for .bmap files. ....."
  817.        
  818.        'GRAHPICS-library
  819.        DECLARE FUNCTION AskSoftStyle& LIBRARY
  820.        DECLARE FUNCTION SetSoftStyle& LIBRARY
  821.        DECLARE FUNCTION OpenFont& LIBRARY
  822.        DECLARE FUNCTION AllocRaster& LIBRARY
  823.        
  824.        'EXEC-library
  825.        DECLARE FUNCTION DoIO& LIBRARY
  826.        DECLARE FUNCTION OpenDevice& LIBRARY
  827.        DECLARE FUNCTION AllocSignal& LIBRARY
  828.        DECLARE FUNCTION FindTask& LIBRARY
  829.        DECLARE FUNCTION AllocMem& LIBRARY
  830.        
  831.        'DISKFONT-library
  832.        DECLARE FUNCTION OpenDiskFont& LIBRARY
  833.        DECLARE FUNCTION AvailFonts& LIBRARY
  834.        
  835.        'LAYERS-library
  836.        DECLARE FUNCTION CreateBehindLayer& LIBRARY
  837.        DECLARE FUNCTION UpFrontLayer& LIBRARY
  838.        DECLARE FUNCTION BehindLayer& LIBRARY
  839.        
  840.        LIBRARY "layers.library"
  841.        LIBRARY "grahpics.library"
  842.        LIBRARY "exec.library"
  843.        LIBRARY "intuition.library"
  844.        LIBRARY "diskfont.library"
  845.        
  846.        setup: '* Here we go.
  847.            PRINT "Paint-1024 Drawing Program."
  848.            PRINT "---------------------------"
  849.            PRINT 
  850.            PRINT "Do you want to work with LoRes(1) or HiRes(2) Screen."
  851.            PRINT "(has no effect on the size of the drawing area) ?    "
  852.            PRINT 
  853.            LINE INPUT "Enter Choice (1 or 2) ---> ";yn$
  854.            IF yn$ = "2" THEN
  855.               scrWidth% = 640
  856.               scrMode%  = 2
  857.            ELSE
  858.               scrWidth% = 320
  859.               scrMode%  = 1
  860.            END IF
  861.        
  862.        initPar:    '* SCreen parameters.
  863.            scrHeight%   = 200
  864.            scrDepth%    = 1
  865.            scrNr%       = 1
  866.        
  867.                             PAGE 294
  868.        
  869. -----------------------------------------------------------------------------
  870.               
  871.            WBenchScrNr%     = -1
  872.            
  873.            '* Window parameters.
  874.            windWidth%   = scrWidth%-9
  875.            windHeight%  = scrHeight%-26
  876.            windNr%      = 1
  877.            windTitle$   = "Working Area"
  878.            windMode%    = 16
  879.            
  880.            '* Window Gadgets.
  881.            Xoffset%     = 15
  882.            GadX%        = windWidth%-Xoffset%+3
  883.            GadY%        = 11
  884.            GadSX%       = Xoffset%-3
  885.            GadSY%       = GadSX%-1
  886.            GadNumber%   = 5
  887.            GadTolerance%= 1
  888.            Gad$(0)      = "^"
  889.            Gad$(1)      = "v"
  890.            Gad$(2)      = "<"
  891.            Gad$(3)      = ">"
  892.            Gad$(4)      = "H"
  893.            
  894.            '* CAD superbitmap.
  895.            superWidth%  = 800
  896.            superHeight% = 400
  897.            superFlag%   =   4
  898.            
  899.            '* Layer size.
  900.            layMinX%     = 3
  901.            layMinY%     =11
  902.            layMaxX%     = winWidth%-8-Xoffset%
  903.            layMaxY%     = windHeight%
  904.        
  905.            '* Drawing modes
  906.            draw%        = 4
  907.            mode$        = "FREEHAND"
  908.            drMd%        = 0
  909.            style%       = 0
  910.            swapper%     = 1
  911.            kl%          = 1
  912.            grid1%       = 1
  913.            grid2%       = 1
  914.            font.height% = 8
  915.            DIM get.array%(1)
  916.            
  917.            '* Printer parameters.
  918.            printX0%     = 0
  919.            printY0%     = 0
  920.            printX1%     = superWidth%
  921.            printY1%     = superHeight%
  922.            printSpec%   = 4
  923.        
  924.        initDisp: '* Open screen and window.
  925.            SCREEN scrNr%,scrWidth%,scrHeight%,scrDepth%,scrMode%
  926.            WINDOW windNr%,windTitle$,(0,0)-(windWidth%,windHeight%),
  927.    windMode%,scrNr%
  928.            WINDOW OUTPUT windNr%
  929.            PALETTE 1,0,0,0
  930.            PALETTE 0,1,1,1
  931.        
  932.                             PAGE 295
  933.        
  934. -----------------------------------------------------------------------------
  935.        
  936.            DIM area.pat%(3):DIM full%(1)
  937.            area.pat%(0) = &H1111
  938.            area.pat%(1) = &H2222
  939.            area.pat%(2) = &H4444
  940.            area.pat%(3) = &H8888
  941.            PATTERN ,area.pat%
  942.            PAINT (100,50),1,1
  943.            full%(0) = &HFFFF
  944.            full%(1) = full%(0)
  945.            PATTERN, full%
  946.        
  947.            '* Prepar TmpRas.
  948.            buffersize& = superWidth%*superHeight%/8
  949.            buffer&     = PEEKL(WINDOW(8)+12)
  950.            IF buffer&<>0 THEN
  951.                 fillflag% = 1
  952.                 mem&      = PEEKL(buffer&)
  953.                 size&     = PEEKL(buffer&+4)
  954.                 CALL FreeMem(mem&,size&)
  955.                 opt& = 2^0+2^1+2^16
  956.                 buf& = AllocMem&(buffersize&,opt&)
  957.                 IF buf&=0 THEN
  958.                    fillflag% = 0
  959.                    POKEL WINDOW(8)+12,0
  960.                 ELSE
  961.                    POKEL buffer&,buf&
  962.                    POKEL buffer&+4,buffersize&
  963.                 END IF
  964.            ELSE
  965.                 fillflag%=0
  966.            END IF
  967.            
  968.        initsys: '* Read system parameters.
  969.            windAdd&    = WINDOW(7)
  970.            scrAdd&     = PEEKL(windAdd&+46)
  971.            scrViewPort&= scrAdd&+44
  972.            scrColMap&  = PEEKL(scrViewPort&+4)
  973.            scrBitMap&  = scrAdd&+184
  974.            scrLayerInfo&=scrAdd&+224
  975.            scrMode%    = PEEKW(scrViewPort&+32)
  976.            font&       = PEEKL(WINDOW(8)+52)
  977.            
  978.        initSBmap: '* Create Superbitmap.
  979.            opt&        = 2^0+2^1+2^16
  980.            superBitmap&= AllocMem&(40,opt&)
  981.            IF superBitmap& = 0 THEN
  982.                PRINT "mnn, not even 40 bytes?"
  983.                ERROR 7
  984.            END IF
  985.            
  986.            '* Activate superbitmap
  987.            CALL InitBitMap(superBitmap&,scrDepth%,superWidth%,superHeight%)
  988.            superPlane& = AllocRaster&(superWidth%,superHeight%)
  989.            IF superPlane& = 0 THEN
  990.                PRINT "No room!"
  991.                CALL FreeMem(superBitmap&,40)
  992.                ERROR 7
  993.            END IF
  994.            POKEL superBitmap&+8,superPlane&
  995.        
  996.                             PAGE 296
  997.        
  998. -----------------------------------------------------------------------------
  999.        
  1000.            '* Open SuperBitMap layer.
  1001.            SuperLayer& = CreateBehindLayer&(scrLayerInfo&, scrBitMap&,
  1002.   layMinX%,layMinY%,layMaxX%,layMaxY%,superFlag%,superBitmap&)
  1003.            IF SuperLayer& = 0 THEN
  1004.                PRINT "Unable to create layer!"
  1005.                CALL FreeRaster(superPlane&,superWidth%,superHeight%)
  1006.                CALL FreeMem(superBitmap&,40)
  1007.                ERROR 7
  1008.            END IF
  1009.            
  1010.            '* New Rastport.
  1011.            SuperRast& = PEEKL(SuperLayer&+12)
  1012.            
  1013.        initPrint: '* Printer initialisation.
  1014.            opt&       = 2^0+2^16
  1015.            pio&       = AllocMem&(100,opt&)
  1016.            IF pio&<>0 THEN
  1017.                port& = pio&+62
  1018.                sigBit% = AllocSignal&(-1)
  1019.                IF sigBit%<>-1 THEN
  1020.                    sigTask& = FindTask&(0)
  1021.                    POKE   port&+8,4
  1022.                    POKEL  port&+10,port&+34
  1023.                    POKE   port&+15,sigBit%
  1024.                    POKEL  port&+16,sigTask&
  1025.                    POKEL  port&+20,port&+24
  1026.                    POKEL  port&+28,port&+20
  1027.                    POKEL  port&+34,1347572736&
  1028.                    CALL AddPort(port&)
  1029.                    POKE  pio&+8,5
  1030.                    POKEL pio&+14,port&
  1031.                    POKEW pio&+18,12
  1032.                    POKEW pio&+28,11
  1033.                    POKEL pio&+32,SuperRast&
  1034.                    POKEL pio&+36,scrColMap&
  1035.                    POKEL pio&+40,scrMode%
  1036.                    POKEW pio&+48,superWidth%
  1037.                    POKEW pio&+50,superHeight%
  1038.                    POKEL pio&+52,superWidth%
  1039.                    POKEL pio&+56,superHeight%
  1040.                    POKEW pio&+60,4
  1041.                ELSE
  1042.                    printflag%   = 1
  1043.                    CALL FreeMem(pio&,100)
  1044.                END IF
  1045.            ELSE
  1046.                printflag% = 1
  1047.            END IF
  1048.        
  1049.        prepare: '* Draw move gadgets.
  1050.            CALL SetDrMd(WINDOW(8),5)
  1051.            FOR loop% = 0 TO GadNumber%-1
  1052.                LINE (GadX%,GadY%+(GadSY%+5)*loop%)-(GadX%+GadSX%,GadY%+
  1053.    GadSY%+(GadSY%+5)*loop%),1,bf
  1054.                gadMouse%(loop%) = GadY%+(GadSY%+5)*loop%-4-GadTolerance%
  1055.                CALL Move(WINDOW(8),GadX%+3,GadY%+((GadSY%+5)*loop%)+8)
  1056.                PRINT Gad$(loop%)
  1057.        
  1058.                             PAGE 297
  1059.        
  1060. -----------------------------------------------------------------------------
  1061.               
  1062.            NEXT loop%
  1063.            CALL SetDrMd(WINDOW(8),1)
  1064.            
  1065.            '* Prepare drawing area.
  1066.            CALL SetRast(SuperRast&,0)
  1067.        
  1068.            '* Draw calibrations.
  1069.            FOR loop% = 0 TO winWidth%-Xoffset% STEP 3
  1070.                IF loop%/15= INT(loop%/15) THEN
  1071.                    LINE (loop%,windHeight%)-(loop%,windHeight%-10)
  1072.                ELSE
  1073.                    LINE (loop%,windHeight%)-(loop%,windHeight%-5)
  1074.                END IF
  1075.            NEXT loop%
  1076.            FOR loop% = 0 TO windHeight% STEP 2
  1077.                IF loop%/10 = INT(loop%/10) THEN
  1078.                    LINE (winWidth%-Xoffset%,loop%)-(winWidth%-10-Xoffset%,
  1079.  loop%)
  1080.                ELSE
  1081.                    LINE (winWidth%-Xoffset%,loop%)-(winWidth%-5-Xoffset%,
  1082.  loop%)
  1083.                END IF
  1084.            NEXT loop%
  1085.            
  1086.            '* Display layer.
  1087.            e&  = UpFrontLayer&(scrLayerInfo&,SuperLayer&)
  1088.            GOSUB newpointer
  1089.        
  1090.            '* Protect and integrate layer.
  1091.            POKEL SuperLayer&+40,windAdd&
  1092.            backup.rast&  = PEEKL(SuperLayer&+12)
  1093.            backup.layer& = PEEKL(WINDOW(8))
  1094.            POKEL SuperLayer&+12,WINDOW(8)
  1095.            POKEL WINDOW(8),SuperLayer&
  1096.            SuperRast& = WINDOW(8)
  1097.            
  1098.            GOSUB coord
  1099.            
  1100.            '* Menu control.
  1101.            MENU 1,0,1,"Service"
  1102.             MENU 1,1,1,"Clear Screen    "
  1103.             MENU 1,2,1,"Coordinates On  "
  1104.             MENU 1,3,1,"----------------"
  1105.             MENU 1,4,1,"Transparent     "
  1106.             MENU 1,5,1,"JAM 2           "
  1107.             MENU 1,6,1,"Complement      "
  1108.             MENU 1,7,1,"Inverse         "
  1109.             MENU 1,8,1,"----------------"
  1110.             MENU 1,9,1,"normal/reset    "
  1111.             MENU 1,10,1,"italic          "
  1112.             MENU 1,11,1,"bold            "
  1113.             MENU 1,12,1,"underline       "
  1114.             MENU 1,13,1,"outline         "
  1115.             MENU 1,14,1,"----------------"
  1116.             MENU 1,15,1,"s/w -> w/s      "
  1117.             MENU 1,16,1,"Title bar on/off"
  1118.             MENU 1,17,1,"QUIT            "
  1119.            MENU 2,0,1,"Draw"
  1120.             MENU 2,1,1,"Circle       "
  1121.             MENU 2,2,1,"Square       "
  1122.             MENU 2,3,1,"Lines        "
  1123.             MENU 2,4,1,"FreeHand     "
  1124.        
  1125.                             PAGE 298
  1126.        
  1127. -----------------------------------------------------------------------------
  1128.            
  1129.             MENU 2,5,1,"Text      "
  1130.             MENU 2,6,1,"Erase     "
  1131.             MENU 2,7,fillflag%,"Fill     "
  1132.             MENU 2,8,1,"Raster/Grid"
  1133.             MENU 2,9,1,"Grid Reset"
  1134.             MENU 2,10,1,"Get Area   "
  1135.             MENU 2,11,1,"Paint Area "
  1136.            MENU 3,0,1,"Font"
  1137.             MENU 3,1,1,"Load Fonts"
  1138.            MENU 4,0,1,"I/O"
  1139.             MENU 4,1,1,"Print    "
  1140.             MENU 4,2,1,"Param.   "
  1141.        
  1142.            ON MENU GOSUB MenuCtrl
  1143.            MENU ON
  1144.        
  1145.        mcp: '* Master Control Program.
  1146.            WHILE forever=forever
  1147.                test% = MOUSE(0)
  1148.                mx%   = MOUSE(1)
  1149.                my%   = MOUSE(2)
  1150.                GOSUB updateDisp
  1151.                CALL SetDrMd(SuperRast&,drMd%)
  1152.                enable% = AskSoftStyle&(SuperRast&)
  1153.                n& = SetSoftStyle&(SuperRast&,style&,enable%)
  1154.            
  1155.                '* Drawing.
  1156.                IF mx%>layMinX% AND mx%<layMaxX% AND test%<0 THEN
  1157.                    IF draw% = 4 THEN
  1158.                        GOSUB freedraw
  1159.                    ELSEIF draw% = 10 THEN
  1160.                        GOSUB paintdraw
  1161.                    ELSEIF draw% = 5 THEN
  1162.                        GOSUB drawtext
  1163.                    ELSEIF draw% = 7 THEN
  1164.                        GOSUB filler
  1165.                    ELSE 
  1166.                        GOSUB drawit
  1167.                        IF draw%=3 AND fetch% = 1 THEN
  1168.                            printX0%  = cX%+subox%
  1169.                            printX1%  = 1+cX%+subox%+oldrcX%
  1170.                            printY0%  = cY%+suboy%
  1171.                            printY1%  = 1+cY%+suboy%+oldrcY%
  1172.                            GOTO continue
  1173.                        ELSEIF draw% = 3 AND grid% = 1 THEN
  1174.                            x1% = cX%+subox%
  1175.                            y1% = cY%+suboy%
  1176.                            x2% = cX%+subox%+oldrcX%
  1177.                            y2% = cY%+suboy%+oldrcY%
  1178.                            IF x1%>x2% THEN SWAP x1%,x2%
  1179.                            IF y1%>y2% THEN SWAP y1%,y2%
  1180.                            g.width%    = x2%-x1%
  1181.                            g.height%   = y2%-y1%
  1182.                            IF copy% = 0 THEN
  1183.                                grid1% = g.width%
  1184.                                grid2% = g.height%
  1185.                            ELSE
  1186.                                g.size&+6+(g.height%+1)*2*INT(g.width%+16)/16)
  1187.                                IF g.size&>(FRE(0)-1000) THEN
  1188.                                    BEEP
  1189.                                ELSE
  1190.        
  1191.                             PAGE 299
  1192.        
  1193. -----------------------------------------------------------------------------
  1194.        
  1195.                                    ERASE get.array%
  1196.                                    DIM get.array%(g.size&/2)
  1197.                                    GET (x1%,y1%)-(x2%,y2%),get.array%
  1198.                                END IF
  1199.                            END IF
  1200.                        END IF
  1201.                    END IF
  1202.                ELSE IF (test%<0 AND mx%>layMaxX%) THEN
  1203.                    '* Scroll gadgets in use ?
  1204.                    IF my%>gadMouse%(4) THEN
  1205.                        GOSUB ScrollHome
  1206.                    ELSEIF my%>gadMouse%(3) THEN '<-
  1207.                        GOSUB ScrollLeft
  1208.                    ELSEIF my%>gadMouse%(2) THEN '->
  1209.                        GOSUB ScrollRight
  1210.                    ELSEIF my%>gadMouse%(1) THEN 'up
  1211.                        GOSUB ScrollUp
  1212.                    ELSEIF my%>gadMouse%(0) THEN 'down
  1213.                        GOSUB ScrollDown
  1214.                    END IF
  1215.                END IF
  1216.            WEND
  1217.        
  1218.        deleteSys: '* remove system
  1219.            buf& = PEEKL(WINDOW(8)+12)
  1220.            IF buf&<>0 THEN
  1221.                buffer& = PEEKL(buf&)
  1222.                size& = PEEKL(buf&+4)
  1223.                CALL FreeMem(buffer&,size&)
  1224.                POKEL WINDOW(8)+12,0
  1225.            END IF
  1226.            IF ptr&<>0 THEN
  1227.                CALL ClearPointer(WINDOW(7))
  1228.                CALL FreeMem(ptr&,20)
  1229.            END IF
  1230.            POKEL SuperLayer&+12,backup.rast&
  1231.            POKEL WINDOW(8),backup.layer&
  1232.            POKEL SuperLayer&+40,0
  1233.            
  1234.            CALL DeleteLayer(scrLayerInfo&,SuperLayer&)
  1235.            CALL FreeRaster(superPlane&,superWidth%,superHeight%)
  1236.            CALL FreeMem(superBitmap&,40)
  1237.            
  1238.            SCREEN CLOSE scrNr%
  1239.            WINDOW windNr%,"hi!",,,WBenchScrNr%
  1240.                       
  1241.            IF printflag%<>1 THEN
  1242.                CALL RemPort(port&)
  1243.                CALL FreeSignal(sigbit%)
  1244.                CALL FreeMem(pio&,100)
  1245.            END IF
  1246.            
  1247.            IF oldFont&<>0 THEN CALL CloseFont(oldFont&)
  1248.            LIBRARY CLOSE
  1249.            END
  1250.            
  1251.        '**** That was it. Here are the important subroutines. ****
  1252.            
  1253.        MenuCTrl: '* Menu in use.
  1254.            menuId    = MENU(0)
  1255.            menuItem  = MENU(1)
  1256.        
  1257.                             PAGE 300
  1258.        
  1259. ------------------------------------------------------------------------------
  1260.            
  1261.            IF menuId = 1 THEN
  1262.                IF menuItem  = 1 THEN
  1263.                    CALL SetRast(SuperRast&,0)
  1264.                ELSEIF menuItem = 2 THEN
  1265.                    GOSUB coord
  1266.                ELSEIF menuItem = 4 THEN
  1267.                    drMd% = 0
  1268.                ELSEIF menuItem = 5 THEN
  1269.                    drMd% = drMd% OR 1
  1270.                ELSEIF menuItem = 6 THEN
  1271.                    drMd% = drMd% OR 2
  1272.                ELSEIF menuItem = 7 THEN
  1273.                    drMd% = drMd% OR 4
  1274.                ELSEIF menuItem = 9 THEN
  1275.                    style%=0:drMd%=0:outline%=0
  1276.                ELSEIF menuItem = 10 THEN
  1277.                    style% = style% OR 4
  1278.                ELSEIF menuItem = 11 THEN
  1279.                    style% = style% OR 2
  1280.                ELSEIF menuItem = 12 THEN
  1281.                    style% = style% OR 1
  1282.                ELSEIF menuItem = 13 THEN
  1283.                    outline% = 1
  1284.                ELSEIF menuItem = 15 THEN
  1285.                    GOSUB swapcol
  1286.                ELSEIF menuItem = 16 THEN
  1287.                    IF k1% = 0 THEN
  1288.                        k1% = 1
  1289.                    ELSE
  1290.                        k1% = 0
  1291.                    END IF
  1292.                ELSEIF menuItem = 17 THEN
  1293.                    GOTO deleteSys
  1294.                END IF
  1295.            ELSEIF menuId = 2 THEN
  1296.                grid% = 0
  1297.                copy% = 0
  1298.                IF menuItem  = 1 THEN
  1299.                    mode$ = "CIRCLE"
  1300.                    draw% = 1
  1301.                ELSEIF menuItem = 2 THEN
  1302.                    mode$ = "SQUARE"
  1303.                    draw% = 3
  1304.                ELSEIF menuItem = 3 THEN
  1305.                    mode$ = "LINES"
  1306.                    draw% = 2
  1307.                ELSEIF menuItem = 4 THEN
  1308.                    mode$ = "FREEHAND"
  1309.                    draw% = 4
  1310.                ELSEIF menuItem = 5 THEN
  1311.                    mode$ = "TEXT"
  1312.                    draw% = 5
  1313.                ELSEIF menuItem = 6 THEN
  1314.                      mode$ = "DELETE"
  1315.                    draw% = 6
  1316.                ELSEIF menuItem = 7 THEN
  1317.                    mode$ = "FILL"
  1318.                    draw% = 7
  1319.                ELSEIF menuItem = 8 THEN
  1320.                    mode$ = "GRID"
  1321.        
  1322.                             PAGE 301
  1323.        
  1324. -----------------------------------------------------------------------------
  1325.  
  1326.                    grid% = 1
  1327.                    draw% = 3
  1328.                ELSEIF menuItem = 9 THEN
  1329.                    grid1% = 1
  1330.                    grid2% = 1
  1331.                ELSEIF menuItem = 10 THEN
  1332.                    mode$ = "GET AREA"
  1333.                    draw% = 3
  1334.                    grid% = 1
  1335.                    copy% = 1
  1336.                ELSEIF menuItem = 11 THEN
  1337.                    mode$ = "PAINT"
  1338.                    draw% = 10
  1339.                END IF
  1340.            ELSEIF menuId = 3 THEN
  1341.                IF fontflag% = 0 THEN
  1342.                    GOSUB loadFonts
  1343.                ELSE
  1344.                    GOSUB loadFont
  1345.                END IF
  1346.            ELSEIF menuId = 4 THEN
  1347.                IF menuItem = 1 THEN
  1348.                    IF printflag%<>1 THEN
  1349.                        GOSUB hardcopy
  1350.                    ELSE 
  1351.                        BEEP
  1352.                    END IF
  1353.                ELSEIF menuItem=2 THEN
  1354.                    GOSUB changePrint
  1355.                END IF 
  1356.            END IF
  1357.            
  1358.            IF k1% = 1 THEN
  1359.                tboff$ = mode$+" / Titlebar Off"+CHR$(0)
  1360.                CALL WaitTOF
  1361.                CALL SetWindowTitles(windAdd&,SADD(tboff$),-1)
  1362.            END IF
  1363.        
  1364.            RETURN
  1365.            
  1366.        coord: '* Show coordinates intersection.
  1367.            CALL SetDrMd(WINDOW(8),2)
  1368.            POKEW SuperRast&+34,&HAAAA
  1369.            FOR loop% = 0 TO superWidth% STEP 50
  1370.                LINE (loop%,0)-(loop%,superHeight%)
  1371.            NEXT loop%
  1372.            FOR loop%=0 TO superHeight% STEP 50
  1373.                LINE (loop%,0)-(superWidth%,loop%)
  1374.            NEXT loop%
  1375.            POKEW SuperRast&+34,&HFFFF
  1376.            CALL SetDrMd(WINDOW(8),drMd%)
  1377.            RETURN
  1378.            
  1379.        drawit: '* Multifunction Drawing with rubberbanding.
  1380.            cX% = MOUSE(1)
  1381.            cY% = MOUSE(2)
  1382.            test% = MOUSE(0)
  1383.            mx%=1:my%=1
  1384.            ccX%=0:ccY%=0
  1385.            oldcX%=0:oldcY%=0
  1386.            rcX%=0:rcY%=0
  1387.            oldrcX%=0:oldrcY%=0
  1388.        
  1389.                             PAGE 302
  1390.        
  1391. -----------------------------------------------------------------------------
  1392.        
  1393.           CALL SetDrMd(SuperRast&,2)
  1394.           subox% = ox%
  1395.           suboy% = oy%
  1396.           loopflag% = 0
  1397.           IF (cX% MOD grid1%) > (.5*grid1%) THEN cX%=cX%+grid1%
  1398.           IF (cY% MOD grid2%) > (.5*grid2%) THEN cY%=cY%+grid2%
  1399.           cX% = cX% - (cX% MOD grid1%)
  1400.           cY% = cY% - (cY% MOD grid2%)
  1401.           GOSUB oldpos
  1402.            
  1403.           WHILE test% < 0 
  1404.                test%=MOUSE(0)
  1405.                oldx%=mx%
  1406.                oldy%=my%
  1407.                oldcX%=ccX%
  1408.                oldCy%=ccY%
  1409.                oldrcX%=rcX%
  1410.                oldrcY%=rcY%
  1411.                mx% = MOUSE(1)
  1412.                my% = MOUSE(2)
  1413.                IF (mx% MOD grid1%) > (.5*grid1%) THEN mx% = mx%+grid1%
  1414.                IF (my% MOD grid2%) > (.5*grid2%) THEN my% = my%+grid2%
  1415.                mx% = mx% - (mx% MOD grid1%)
  1416.                my% = my% - (my% MOD grid2%)
  1417.                IF mx%=oldx% AND my%=oldy% AND s.fl%=0 THEN 
  1418.                    rep.flag% = 1
  1419.                ELSE 
  1420.                    rep.flag% = 0
  1421.                    s.fl%     = 0
  1422.                END
  1423.                IF rep.flag% = 0 THEN
  1424.                    GOSUB oldpos
  1425.                END IF
  1426.                IF mx%<layMinX%+5 THEN GOSUB ScrollRight
  1427.                IF mx%>layMaxX%-15 THEN GOSUB ScrollLeft
  1428.                IF my%<layMinY%+5 THEN GOSUB ScrollDown
  1429.                IF my%>layMaxY%-20 THEN GOSUB ScrollUp
  1430.                GOSUB updateDisp
  1431.            
  1432.                ccX%=ABS(mx%-cX%) + ABS(ox%-subox%)
  1433.                ccY%=ABS(my%-cY%) + ABS(oy%-suboy%)
  1434.                rcY% = my%-cY%+(oy%-suboy%)
  1435.                rcX% = mx%-cX%+(ox%-subox%)
  1436.                IF rep.flag%=0 THEN
  1437.                    GOSUB newpos
  1438.                END IF
  1439.            WEND
  1440.            GOSUB newpos
  1441.            CALL SetDrMd(SuperRast&,1)
  1442.            IF draw% = 6 THEN
  1443.                x1% = cX%+subox%
  1444.                y1% = cY%+suboy%
  1445.                x2% = cX%+subox%+oldrcX%
  1446.                y2% = cY%+suboy%+oldrcY%
  1447.                IF x2%<x1% THEN SWAP x1%,x2%
  1448.                IF y2%<y1% THEN SWAP y1%,y2%
  1449.                x1%=x1%+1:y1%=y1%+1
  1450.        
  1451.                             PAGE 303
  1452.        
  1453. -----------------------------------------------------------------------------
  1454.        
  1455.                x2%=x2%-1:y2%=y2%-1
  1456.                CALL SetAPen(WINDOW(8),0)
  1457.                CALL RectFill(WINDOW(8),x1%,y1%,x2%,y2%)
  1458.                CALL SetAPen(WINDOW(8),1)
  1459.            ELSEIF (draw%=3 AND (fetch%<>0 OR grid%<>0)) THEN
  1460.                REM nothing
  1461.            ELSE
  1462.                GOSUB newpos
  1463.            END IF
  1464.        RETURN
  1465.        
  1466.        newpos: 
  1467.            IF draw%=1 THEN
  1468.                CALL DrawEllipse(SuperRast&,cX%+subox%,cY%+suboy%,ccX%,ccY%)
  1469.            ELSEIF draw%=2 THEN
  1470.                LINE (cX%+subox%,cY%+suboy%)-(cX%+subox%+rcX%,cY%+suboy%+
  1471.    rcY%),swapper%
  1472.            ELSEIF draw% = 3 OR draw% = 6 THEN
  1473.                LINE (cX%+subox%,cY%+suboy%)-(cX%+subox%+rcX%,cY%+suboy%+
  1474.    rcY%),swapper%,b
  1475.            END IF
  1476.            RETURN
  1477.            
  1478.        oldpos:
  1479.            IF draw%  = 1 THEN
  1480.                CALL DrawEllipse(SuperRast&,cX%+subox%,cY%+suboy%,oldcX%,
  1481.    oldcY%)
  1482.            ELSEIF draw%=2 THEN
  1483.                LINE (cX%+subox%,cY%+suboy%)-(cX%+subox%+oldrcX%,cY%+suboy%
  1484.    +oldrcY%),swapper%
  1485.            ELSEIF draw%=3 OR draw%=6 THEN
  1486.                LINE (cX%+subox%,cY%+suboy%)-(cX%+subox%+oldrcX%,cY%+suboy%
  1487.    +oldrcY%),swapper%,b
  1488.            END IF
  1489.            RETURN
  1490.            
  1491.        filler: '* Fill routine
  1492.            test% = MOUSE(0)
  1493.            oldx% = MOUSE(1)
  1494.            oldy% = MOUSE(2)
  1495.            PAINT (ox%+oldx%,oy%+oldy%),1,1
  1496.            RETURN
  1497.            
  1498.        freedraw:  '* Freehand drawing.
  1499.            test% = MOUSE(0)
  1500.            oldx% = MOUSE(1)
  1501.            oldy% = MOUSE(2)
  1502.            WHILE test% < 0 
  1503.                oldx% = mx%
  1504.                oldy% = my%
  1505.                mx% = MOUSE(1)
  1506.                my% = MOUSE(2)
  1507.                IF mx%<layMinX%+10 THEN GOSUB ScrollRight
  1508.                IF mx%>layMaxX%-20 THEN GOSUB ScrollLeft
  1509.                IF my%>layMinY%+10 THEN GOSUB ScrollDown
  1510.                IF my%<layMaxY%-25 THEN GOSUB ScrollUp
  1511.                LINE (ox%+oldx%,oy%+oldy%)-(ox%+mx%,oy%+my%),swapper%
  1512.                GOSUB updateDisp
  1513.                test% = MOUSE(0)
  1514.            WEND
  1515.        RETURN
  1516.        
  1517.                             PAGE 304
  1518.        
  1519. -----------------------------------------------------------------------------
  1520.        
  1521.        paintdraw: '*Draw with image.
  1522.            test% = MOUSE(0)
  1523.            WHILE test%<0
  1524.                mx% = MOUSE(1)
  1525.                my% = MOUSE(2)
  1526.                IF mx%<layMinX%+10 THEN GOSUB ScrollRight
  1527.                IF mx%>layMaxX%-20 THEN GOSUB ScrollLeft
  1528.                IF my%<layMinY%+10 THEN GOSUB ScrollDown
  1529.                IF my%>layMaxY%-25 THEN GOSUB ScrollUp
  1530.                mx% = mx%-(mx% MOD grid1%)
  1531.                my% = my%-(my% MOD grid2%)
  1532.                IF mx%<layMinX%+10 THEN GOSUB ScrollRight
  1533.                IF mx%>layMaxX%-20 THEN GOSUB ScrollLeft
  1534.                IF my%<layMinY%+10 THEN GOSUB ScrollDown
  1535.                IF my%>layMaxY%-25 THEN GOSUB ScrollUp
  1536.        
  1537.                test% = MOUSE(0)
  1538.                PUT (mx%+ox%,my%+oy%),get.array%,OR
  1539.            WEND
  1540.        RETURN
  1541.        
  1542.        scrollhome: 
  1543.            x% = -ox%
  1544.            y% = -oy%
  1545.            oy%= 0
  1546.            ox%= 0
  1547.            GOSUB ScrollDisplay
  1548.            RETURN
  1549.            
  1550.       ScrollRight:
  1551.            IF ox%grid1% THEN
  1552.                x% = -grid1%
  1553.                ox% = ox%-grid1%
  1554.                GOSUB ScrollDisplay
  1555.            END IF
  1556.            RETURN
  1557.            
  1558.        ScrollLeft:
  1559.            IF ox%<(superWidth%-layMaxX%+layMinX%-grid1%) THEN
  1560.                x% = grid1%
  1561.                IF textWidth% <> 0 THEN
  1562.                    IF ox%+textWidth%<(superWidth%-layMaxX%+layMin%) THEN
  1563.                        x% = textWidth%
  1564.                    END IF
  1565.                textwidth% = 0
  1566.                END IF
  1567.                ox% = ox%+x%
  1568.                GOSUB ScrollDisplay
  1569.            END IF
  1570.            RETURN
  1571.        
  1572.        scrollUp: 
  1573.            IF oy%<(superHeight%-layMaxY%+layMinY%-grid2%) THEN
  1574.                y% = grid2%
  1575.                oy%= oy%+grid2%
  1576.                GOSUB ScrollDisplay
  1577.            END IF
  1578.            RETURN
  1579.        
  1580.        scrollDown:
  1581.            IF oy%>grid2%-1 THEN
  1582.                y% = -grid2%
  1583.                oy%= oy%-grid2%
  1584.                GOSUB ScrollDisplay
  1585.        
  1586.                             PAGE 305
  1587.        
  1588. -----------------------------------------------------------------------------
  1589.        
  1590.              END IF
  1591.          RETURN
  1592.        
  1593.        ScrollDisplay:'* scroll it
  1594.            CALL ScrollLayer(scrLayerInfo&,SuperLayer&,x%,y%)
  1595.                x%  = 0
  1596.                y%  = 0
  1597.                s.fl%=1
  1598.                RETURN
  1599.        
  1600.        updateDisp:
  1601.            IF k1% = 0 THEN
  1602.                actu$="> "+mode$+" [F]="+STR$(fontHeight%)+" [X]="+STR$
  1603.  (ox%+mx%)+" [Y]="+STR$(oy%+my%)+CHR$(0)
  1604.                CALL WiatTOF
  1605.                CALL SetWindowTitles(winAdd&,SADD(actu$),-1)
  1606.            END IF
  1607.            RETURN
  1608.            
  1609.        loadFonts: '* Load disk fonts.
  1610.            sp$   = mode$
  1611.            mode$ = "LOAD FONTS"
  1612.            GOSUB upddateDisp
  1613.            opt& = 2^0+2^16
  1614.            bufLen& = 3000
  1615.            buffer& = AllocMem&(bufLen&,opt&)
  1616.            IF buffer&<>0 THEN
  1617.                er& = AvailFonts(buffer&,bufLen&,3)
  1618.                IF er& = 0 THEN
  1619.                    fontcnt% = PEEKW(buffer&)
  1620.                    IF fontcnt% > 19 THEN fontcnt% = 19
  1621.                    DIM textAttr&(fontcnt%*2)
  1622.                    DIM textName$(fontcnt%)
  1623.                    FOR loop% = 0 TO fontcnt%-1
  1624.                        counter% = loop%*10
  1625.                        fontTitle& = PEEKL(buffer&+4+counter%)
  1626.                        fontH%     = PEEKW(buffer&+counter%+8)
  1627.                        textAttr&(loop%*2+1)= PEEKL(buffer&+counter%+8)
  1628.                        fontTitle$ = ""
  1629.                        check% = PEEK(fontTitle&)
  1630.                        WHILE check%<>ASC(".")
  1631.                            fontTitle$=fontTitle$+CHR$(check%)
  1632.                            fontTitle&= fontTitle&+1
  1633.                            check%    = PEEK(fontTitle&)
  1634.                        WEND
  1635.                        textName$(loop%) = fontTitle$+".font"+CHR$(0)
  1636.                        fontName$        = fontcounter+1                   
  1637.                        MENU 3,fontcounter,1,fontName$
  1638.                    NEXT loop%
  1639.                    CALL FreeMem(buffer&,buffLen&)
  1640.                    fontflag% = 1
  1641.                END IF
  1642.            ELSE 
  1643.                BEEP
  1644.            END IF
  1645.            mode$ = sp$
  1646.            RETURN
  1647.        
  1648.        loadFont: '* Load font.
  1649.        
  1650.                             PAGE 306
  1651.        
  1652. -----------------------------------------------------------------------------
  1653.        
  1654.            sp$  = mode$
  1655.            mode$ = "LOAD FONT"
  1656.            GOSUB updateDisp
  1657.            textBase% = (menuItem-1)*2
  1658.            textAttr&(textBase%) = SADD(textName$(menuItem-1))
  1659.            newFont& = OpenDiskFont&(VARPTR(textAtrr&(textBase%)))
  1660.            IF newFont& = 0 THEN
  1661.                newFont& = OpenFont&(VARPTR(textAttr&(textBase%)))
  1662.            END IF
  1663.            IF newFont& <> 0 THEN
  1664.                IF oldFont& <> 0 THEN
  1665.                    CALL CloseFont(oldFont&)
  1666.                END IF
  1667.                CALL SetFont(SuperRast&,newFont&)
  1668.                oldFont& = newFont&
  1669.                fontHeight% = INT(textAttr%(textBase%+1)/2^16)
  1670.            ELSE
  1671.                BEEP
  1672.            END IF
  1673.            mode$ = sp$
  1674.            RETURN
  1675.            
  1676.        drawtext: '* Write text in graphic bitmap
  1677.            IF (mx% MOD grid1%) > (.5*grid1%) THEN mx%=mx%+grid1%
  1678.            IF (my% MOD grid2%) > (.5*grid2%) THEN my%=my%+grid2%
  1679.            my%=my%-(my% MOD grid2%)
  1680.            mx%=mx%-(mx% MOD grid1%)
  1681.            CALL Move(SuperRast&,mx%+ox%,my%+oy%+fontHeight%)
  1682.            mode$ = "ENTRY"+CHR$(0)
  1683.            CALL WaitTOF
  1684.            CALL SetWindowTitles(windAdd&,SADD(mode$),-1)
  1685.            mode$ = "TEXT"
  1686.            in$   = ""
  1687.            WHILE in$<> CHR$(13)
  1688.                IF in$<>"" THEN
  1689.                    CALL SetDrMd(SuperRast&,drMd%)
  1690.                    enable% = AskSoftStyle&(SuperRast&)
  1691.                    n& = SetSoftStyle&(SuperRast&,style%,enable%)
  1692.                    tempX% = PEEKW(SuperRast&+36)
  1693.                    tempY% = PEEKW(SuperRast&+38)
  1694.                    rand%  = tempX%-ox%
  1695.                    IF rand%>layMaxX%-20 THEN
  1696.                        textWidth% = PEEKW(SuperRast&+60)
  1697.                        GOSUB ScrollLeft
  1698.                    END IF
  1699.                    IF outline% = 0 THEN
  1700.                        CALL Text(SuperRast&,SADD(in$),1)
  1701.                    ELSE
  1702.                        CALL SetDrMd(SuperRast&,0)
  1703.                        FOR loop1% = -1 TO 1
  1704.                            FOR loop2% = -1 TO 1
  1705.                              CALL Move(SuperRast&,tempX%+loop2%,tempY%+
  1706.    loop1%)
  1707.                              CALL Text(SuperRast&,SADD(in$),1)
  1708.        
  1709.                                 PAGE 307
  1710.        
  1711. -----------------------------------------------------------------------------
  1712.  
  1713.                        NEXT loop2%
  1714.                    NEXT loop1%
  1715.                    CALL SetDrMd(SuperRast&,2)
  1716.                    CALL Move(SuperRast&,tempX%,tempY%)
  1717.                    CALL Text(SuperRast&,SADD(in$),1)
  1718.                    tempW% = 0
  1719.                END IF
  1720.            END IF
  1721.            in$ = INKEY$
  1722.            '*Function key assignments.
  1723.            '* These lines could be used to assign characters
  1724.            '* which are normally unaccessable to the function 
  1725.            '* keys for use in TEXT mode 
  1726.            IF in$ = CHR$(129) THEN in$ = CHR$(49)
  1727.            IF in$ = CHR$(130) THEN in$ = CHR$(50)
  1728.            IF in$ = CHR$(131) THEN in$ = CHR$(51)
  1729.            IF in$ = CHR$(132) THEN in$ = CHR$(52)       
  1730.            IF in$ = CHR$(133) THEN in$ = CHR$(53)
  1731.            IF in$ = CHR$(134) THEN in$ = CHR$(54)
  1732.            IF in$ = CHR$(135) THEN in$ = CHR$(55)
  1733.            IF in$ = CHR$(136) THEN in$ = CHR$(56)
  1734.            IF in$ = CHR$(137) THEN in$ = CHR$(57)
  1735.            IF in$ = CHR$(138) THEN in$ = CHR$(48)
  1736.            WEND
  1737.            m$="TEXT"+CHR$(0)
  1738.            CALL WaitTOF
  1739.            CALL SetWindowTitles(windAdd&,SADD(m$),-1)
  1740.            mx% = 0
  1741.            my% = 0
  1742.            RETURN
  1743.            
  1744.    newpointer: '* Define Drawing Pointer.
  1745.            opt& = 2^1+2^16
  1746.            ptr& = AllocMem&(20,opt&)
  1747.            IF ptr&<>0 THEN
  1748.                POKEW ptr&+4,256
  1749.                POKEW ptr&+8,640
  1750.                POKEW ptr&+12,256
  1751.                CALL SetPointer(WINDOW(7),ptr&,3,16,-8,-1)
  1752.            END IF
  1753.            RETURN
  1754.            
  1755.        hardcopy: '* Print bitmap
  1756.            sp$ = mode$
  1757.            mode$ = "HARDCOPY"
  1758.            GOSUB updateDisp
  1759.            dev$ = "printer.device"+CHR$(0)
  1760.            er&  = OpenDevice&(SADD(dev$),0,pio&,0)
  1761.            IF er& = 0 THEN
  1762.                er& = OpenDevice&(SADD(dev$),0,pio&,0)
  1763.                er& = DoIO&(pio&)
  1764.                IF er&<>0 THEN BEEP:BEEP
  1765.                CALL CloseDevice(pio&)
  1766.            ELSE
  1767.                BEEP
  1768.            END IF
  1769.            mode$ = sp$
  1770.            RETURN
  1771.            
  1772.        swapcol: 
  1773.            IF swapper% = 0 THEN 
  1774.                swapper% = 1
  1775.            ELSE
  1776.        
  1777.                             PAGE 308
  1778.        
  1779. -----------------------------------------------------------------------------
  1780.        
  1781.                swapper% = 0
  1782.            END IF
  1783.        RETURN
  1784.        
  1785.         changePrint: '* Change printer parameters
  1786.                      '* Output to your window.
  1787.            backup.font& = PEEKL(WINDOW(8)+52)
  1788.            CALL SetFont(WINDOW(8),font&)
  1789.            POKEL SuperLayer&+12,backup.rast&
  1790.            POKEL WINDOW(8),backup.layer&
  1791.            e& = BehindLayer&(scrLayerInfo&,SuperLayer&)
  1792.            CALL SetDrMd(WINDOW(8),1)
  1793.            LINE (0,0)-(windWidth%-8-offset%-20,windHeight%-15),1,bf
  1794.            LINE (20,10)-(windWidth%-offset%-40,windHeight%-25),0,bf
  1795.            LOCATE 3,1
  1796.            PRINT TAB(4);"PRINT PARAMETER SETTINGS"
  1797.            PRINT TAB(4);"------------------------"
  1798.            PRINT 
  1799.            PRINT TAB(4);"Outline area to be printed"
  1800.            PRINT TAB(4);"with the frame"
  1801.            PRINT
  1802.            FOR t=1 TO 10000:NEXT t
  1803.            repeat:
  1804.            fetch%  = 1
  1805.            draw%   = 3
  1806.            mode%   = "FETCH"
  1807.        
  1808.            '* output back to the layer *'
  1809.            e& = UpFrontLayer&(scrLayerInfo&,SuperLayer&)
  1810.            POKEL SuperLayer&+12,WINDOW(8)
  1811.            POKEL WINDOW(8),SuperLayer&
  1812.        
  1813.            GOTO mcp
  1814.            
  1815.            continue:
  1816.            fetch% = 0
  1817.            mode$ = "SQUARE"
  1818.            '* Output on your window .
  1819.            e& = BehindLayer&(scrLayerInfo&,SuperLayer&)
  1820.            POKEL SuperLAyer&+12,backup.rast&
  1821.            POKEL WINDOW(8),backup.layer&
  1822.                LOCATE 9,1
  1823.                PRINT TAB(4); USING "New Starting X:####";printX0%
  1824.                PRINT TAB(4); USING "New Starting Y:####";printY0%
  1825.                PRINT TAB(4); USING "New Ending   X:####";printX1%
  1826.                PRINTX1P%= printX1% - printX0%
  1827.                PRINT TAB(4); USING "New Ending   Y:####";printY1%
  1828.                PRINTY1P%= printY1% - printY0%
  1829.            
  1830.                LOCATE 15,1
  1831.                PRINT TAB(4) SPACE$(26)
  1832.                LOCATE 15,1
  1833.                PRINT TAB(4);
  1834.                INPUT "Are the values OK (y/n) ? ";yn$
  1835.            
  1836.                                    PAGE 309
  1837.        
  1838. -----------------------------------------------------------------------------
  1839.        
  1840.               IF yn$ = "n" THEN GOTO repeat
  1841.        
  1842.               PRINT TAB(4);
  1843.               INPUT "[1] Normal  [2] Resised";nv%
  1844.               IF nv% = 2 THEN
  1845.                   PRINT TAB(4);
  1846.                   INPUT "Absolute X Expansion";printX%
  1847.                   PRINT TAB(4);
  1848.                   INPUT "Absolute Y Expansion";printY%
  1849.                   printSpec% = 0
  1850.               ELSE
  1851.                   printSpec% = 4
  1852.               END IF
  1853.        
  1854.               POKEW pio&+44,printX0%
  1855.               POKEW pio&+46,printY0%
  1856.               POKEW pio&+48,printX1P%
  1857.               POKEW pio&+50,printY1P%
  1858.               POKEL pio&+52,printX%
  1859.               POKEL pio&+56,printY%
  1860.               POKEW pio&+60,printSpec%
  1861.        
  1862.               '* Output back to the layer.
  1863.               e& = UpFrontLayer&(scrInfo&,SuperLayer&)
  1864.               POKEL SuperLayer&+12,WINDOW(8)
  1865.               CALL SetFont(WINDOW(8),backup.font&)
  1866.               CALL SetDrMd(WINDOW(8),drMd%)
  1867.        
  1868.               RETURN
  1869.        
  1870.                             PAGE 310
  1871.        
  1872. ------------------------------------------------------------------------
  1873.        
  1874. 8.1 PAINT 1024 PROGRAM INSTRUCTIONS.
  1875.        
  1876. Before you start the program, take a good look at the variable definitions
  1877. at the beginning. You can use either lo-res or hi-res for your working 
  1878. screen. Since this has no effect on the size of the drawing we recommend
  1879. you use the lower resolution.       
  1880.        
  1881. You can choose the size of the superbitmap which means that you will be
  1882. choosing the overall size of the drawing. The current program settings 
  1883. define a 400*800 pixel drawing area. When you have enough memory, you can
  1884. expand this to the full 1024*1024 CAD standard.       
  1885.        
  1886. Starting the Program:
  1887. --------------------
  1888.        
  1889. You start paint-1024 with "RUN". If you have two disk drives put your 
  1890. program in one drive and the Workbench disk in the second drive. For use 
  1891. with single drives start the program and then replace the program disk with
  1892. the Workbench disk. If you receive the message "Please put XXX in drive..."
  1893. you are returned to the workbench screen. To get back to the program screen
  1894. press the left Amiga <A> key and the <M> key simultaneously. Or you can
  1895. simply slide the workbench screen down.
  1896.        
  1897. First Drawing :
  1898. ---------------
  1899.        
  1900. Now you are in the drawing program. The drawing area is the biggest portion 
  1901. of the screen. The title bar is switched off as soon as the program begins.
  1902. Press the right mouse button once and the menu bar appears. The SERVICE
  1903. menu contains:
  1904.        
  1905. ___________________________________________________________________
  1906. | SERVICE         DRAW         FONT      I/O                      |
  1907. -------------------------------------------------------------------
  1908. | Clear Screen   |
  1909. | Coordinates On |
  1910. | -------------- |
  1911. | Transparent    |
  1912. | JAM 2          |
  1913. | Complement     |
  1914. | Inverse        |
  1915. | -------------- |
  1916. | Normal/reset   |
  1917. | Italic         |
  1918. | Bold           |
  1919. | Underline      |
  1920. | Outline        |
  1921. | -------------- |
  1922. | s/w -> w/s     |
  1923. | Title Bar      |
  1924. | On/Off         |
  1925. | QUIT           |
  1926. |________________|
  1927.        
  1928.                             PAGE 311
  1929.        
  1930. ------------------------------------------------------------------------
  1931.        
  1932. The first menu selection clears the entire drawing. The second selection
  1933. switches on a coordinate grid. If you select this item a second time the
  1934. grid is removed.
  1935.        
  1936. The next nine items determine the method of text display, which we will
  1937. discuss shortly. The s/w and w/s switch exchanges the back and foreground
  1938. colours. This can be very helpful when you want to delete only part of 
  1939. your drawing.
  1940.        
  1941. Try selecting "Titlebar on/Off" once. The actual mouse position will be
  1942. displayed in the title bar along with the active drawing mode and the 
  1943. height of the current font. The title bar requires a lot of calculation 
  1944. time to keep it updated. Also, the scrolling and drawing functions will
  1945. slow down when the title bar displays the mouse coordinates. So, when you
  1946. can do without the title bar leave it switched off.
  1947.        
  1948. When the program starts you will be in FREEHAND drawing mode. As soon as
  1949. you press the left mouse button you will be drawing. When you get close to 
  1950. the right or lower border, the screen begins scrolling. Additional portions
  1951. of the superbitmap become visible if you are not already at a border of the
  1952. plane.       
  1953.        
  1954. In the right screen border you will find five small icons. Move onto one of
  1955. them with the mouse and press the left button. The screen scrolls in the 
  1956. direction indicated by the arrow if there is anything to move. The H 
  1957. symbol stands for Home and, with incredible speed, will return the drawing
  1958. to it's original position.
  1959.        
  1960. Circles, Lines and Squares :
  1961. ----------------------------
  1962.        
  1963. Under the menu item DRAW are the different drawing functions. As long as 
  1964. you hold down the left mouse button you can set the size and direction of 
  1965. the selected drawin function. Releasing the button draws the object.
  1966.        
  1967. Please remember that the Circle command only functions with Kickstart 
  1968. Version 1.2 or higher.
  1969.        
  1970.        
  1971. Erase a Portion of the Drawing :
  1972. --------------------------------
  1973.        
  1974. To delete only a portion of your drawing select ERASE. You can then select 
  1975. a rectangular portion of your drawing that will be replaced with the 
  1976. background colour.
  1977.        
  1978.        
  1979. Text Output :
  1980. -------------
  1981.        
  1982. Use this option to add the text to your drawing. After you activate the 
  1983. TEXT mode you can still move around with the mouse. When you press the left
  1984. mouse button the Amiga expects text to be entered through the keyboard. To
  1985. end text entry, press the <Enter> key. The function keys are currently 
  1986. assigned to the numbers 0 thru 9. They can be reassigned in the program to 
  1987. contain special characters of the Amiga fonts.
  1988.        
  1989.                             PAGE 312
  1990.        
  1991. --------------------------------------------------------------------------
  1992.        
  1993. The SERVICE menu provides you with many text modes:
  1994.        
  1995. Transparent:   Text does not delete graphics.
  1996. JAM2       :   Text overwrites graphics.
  1997. Complement :   What is black becomes white and vice versa.
  1998. Inverse    :   Back and foreground colours are swapped (only functions 
  1999.                in normal text mode).
  2000. Normal     :   All text styles are switched off.
  2001. Italic     :   Slanted Text.
  2002. Bold       :   Bold text.
  2003. Outline    :   Silhouette text.
  2004.        
  2005. The text styles can be mixed by selecting more than one style. It is also
  2006. possible to change styles while you are in text output mode.
  2007.        
  2008. Pressing <Enter> ends the text output mode.
  2009.        
  2010. If you want to enter more than one line of text and align the entire text,
  2011. switch on the GRID. Select the X direction width of one character of the 
  2012. font and the Y direction height (more information about GRID follows).
  2013. End each line with <Enter>. To start the next line, move the mouse to the
  2014. desired position and press the left button.
  2015.        
  2016.        
  2017. Using Different Fonts :
  2018. -----------------------
  2019.        
  2020. The FONT menu allows you to use disk fonts for your text output. The first 
  2021. time you use this menu item you will see LoadFonts. Before you select 
  2022. this menu item you should insert the workbench disk that contains your 
  2023. fonts into one of your drives. When LoadFonts is selected it will search 
  2024. for all the usable fonts (19 is the maximum number the menu will handle).
  2025. The next time you click this menu item, it will contain a list of 
  2026. available fonts. You can select any font from this list. The TEXT item of
  2027. the DRAW menu uses the last selected font.
  2028.        
  2029.        
  2030. Graphic Font :
  2031. --------------
  2032.        
  2033. If you have a graphic-capable printer, you can print out your drawing.
  2034. The I/O menu contains the PRINT and PARAM options. To print the entire
  2035. drawing plane, simply select PRINT. If you want to print only a portion 
  2036. of the drawing, select Param. This menu item allows you to select a section
  2037. of your drawing by using a rectangular-rubberband method that frames the 
  2038. area you want printed with a rectangle. The selected area is displayed and
  2039. you can make any needed corrections. Once the section is correct, you can
  2040. choose between (1) Normal Print and (2) Distorted print. Normal print 
  2041. produces the graphic in its normal proportions. Distorted print allows you 
  2042. to specify the number of pixels in X and Y directions, that the printed
  2043. output should use. If you specify more pixels in the horizontal direction
  2044. than your printer is able to print, then nothing will be printed.
  2045.        
  2046.                             PAGE 313
  2047.        
  2048. ---------------------------------------------------------------------------
  2049.        
  2050. During printing all graphic functions are switched off.
  2051.        
  2052.        
  2053. Raster/Grid :
  2054. -------------
  2055.        
  2056. Often, it is necessary to create symmetrical drawings or diagrams. The 
  2057. Rastre/Grid menu allows you to create a drawing grid of any size. Simply 
  2058. selet the grid square size that you need. From this point on, all drawing
  2059. operations will function according to this grid. You can change this grid
  2060. size at any time. GRID RESET returns the grid to a 1*1 pixel size which is 
  2061. the default drawing mode.
  2062.        
  2063.        
  2064. Area Fill :
  2065. -----------
  2066.        
  2067. The FILL function lets you fill areas of any size. First the area to be 
  2068. filled must be framed completely with a black line that has no gaps. Place 
  2069. the mouse in the middle of the area to be filled and press the left mouse 
  2070. button. When filling in very large areas, and when working with large 
  2071. objects in the drawing area, this operation can take over a minute to 
  2072. complete.
  2073.        
  2074. User Defined Brushes :
  2075. ----------------------
  2076.        
  2077. You can select a piece of your drawing to use as a brush. The size of th
  2078. brush is limited only by the available memory. To do this, select GET AREA 
  2079. from the DRAW menu. Now you can frame the desired area and "grab it". You
  2080. can draw with this area by using Paint Area.
  2081.        
  2082.        
  2083. User Defined Patterns :
  2084. -----------------------
  2085.        
  2086. The way patterns work is quite similar to brush. You can define any portion
  2087. of your graphic as a pattern. To do this, draw a small sample of the pattern
  2088. and grab it using Get Area. Now grab the same piece again using the Raster 
  2089.  / Grid menu item and then select Paint Area. Now you can use your pattern
  2090. as a brush to paint on the screen.
  2091.        
  2092.                             PAGE 314
  2093.        
  2094. --------------------------------------------------------------------------
  2095.        
  2096.                       GRAPHIC PROGRAMMING IN 'C'
  2097.                       ==========================
  2098.        
  2099. You have probably noticed that although BASIC can create fantastic graphics,
  2100. it is quite slow. It is obvious that BASIC just doesnt have the speed that 
  2101. we need to create fast graphics. However, if we use machine code, we could
  2102. gain more speed, but machine language can be difficult to program.
  2103.        
  2104. The high level language 'C' is perfct for this type of programming. This 
  2105. language offers the speed usually attained only with machine language and
  2106. the simplicity of a programming language like BASIC.
  2107.        
  2108. Since we do not want to repeat the infomation provided in the first section
  2109. of this book, in this chapter, we will only discuss the C characteristics
  2110. for graphic programming.
  2111.        
  2112. The programs in this section were written using three compilers. Aztec C 
  2113. V3.6a, Lattice C V5 and one using the Lattice C V3.10 compiler. Minor 
  2114. changes may have to be made to compile the prorams on different compilers.
  2115. See you compiler documentation for more information. Please remember to 
  2116. raise the system stack to 1024 bytes (CLI Command: stack 1024). Now we will
  2117. present the required elements for graphic programming in 'C'.
  2118.        
  2119.                             PAGE 315
  2120.        
  2121. ----------------------------------------------------------------------------
  2122.        
  2123. The Amiga Libraries.
  2124. ====================
  2125.        
  2126. Since learning a new computr language can be difficult, we will concentrate
  2127. only on graphic programming with C and not on learning the C langauge. If
  2128. certain terms such as Cast and Struct are confusing, please refer to the 
  2129. Abacus book, Amiga C for Beginners (** Complete Book is one *-ALLIANCE-* Dox
  2130. Disk One !!...hehehe) or another book on Amiga C.
  2131.        
  2132. Before you can use C's graphic functions, which are not part of the standard
  2133. C functions, first you have to learn about the Amiga libraries.
  2134.        
  2135. Each library contains a series of jump addresses for the individual graphic
  2136. ROM routines. Since there are different ROM versions (kickstarts) for the 
  2137. Amiga, the library concept is very useful. Every library has its own memory  
  2138. section that places a routine at a specific address. This means that a 
  2139. routine can be at a different address in each KickStart version. These 
  2140. addresses are found in the libraries. This allows a program to work with 
  2141. Kickstart 1.2 and 1.3 (and now 2.0) even though the routines are in 
  2142. different locations.
  2143.        
  2144. There are libraries for many different purposes. For us, the most important 
  2145. library is the graphics library. You open the graphics library like this:
  2146.        
  2147.        GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",0)
  2148.        
  2149. GfxBase is the structure that contains all the important library 
  2150. information. The OpenLibrary funtion passes a pointer for this information 
  2151. to an initialised GfxBase structure that must be named GfxBase. At the same
  2152. time, the string "graphics.library" is the name of the graphics library. 
  2153. The zero in the parameter list for OpenLibrary specifies the current version
  2154. of the library, which is the one that we want to open.
  2155.        
  2156. Now that we have opened the graphics library we can return to graphic
  2157. programming. First we must create an area where we can display and save
  2158. our graphics.
  2159.        
  2160. Let's compare our operations to those of a large factory.
  2161.        
  2162.                                    PAGE 316
  2163.        
  2164. -----------------------------------------------------------------------------
  2165.        
  2166. 9.2  THE VIEW
  2167. =============
  2168.        
  2169. View should already be familiar to you from the first two sections of this 
  2170. book. However, since View is so important, we will briefly discuss it again.
  2171.        
  2172. View is the link between our creativity and the computer. The structure
  2173. strut View contains all the necessary View data.
  2174. Use InitView(&View) to intialise the View structure for all the individual 
  2175. variables.
  2176.        
  2177. -----------------------------------------------------------------------------
  2178.        
  2179. 9.3 The Foreman: The VIEWPORT
  2180. =============================
  2181.        
  2182. This is where you determine the size of the creativity area, the display 
  2183. mode and the available colours. All of this data is sent to the ViewPort.
  2184. This data is later used to create the Copper list that the special Copper
  2185. coprocessor will use to construct your screen.
  2186.        
  2187. Before you can send data to the ViewPort you must first specify the 
  2188. position on screen at which data should appear. The variables View.DxOffset
  2189. and View.DyOffset establish this position on the screen: One sets the 
  2190. X-coordinate on the screen, while the other sets the Y-ccordinate. InitView
  2191. initialises these variables so that your View position matches the 
  2192. positionin set in the Preferences (i.e. The corner angle in your preferences
  2193. screen which helps centre the screen).
  2194.        
  2195. If you enter a zro valu for ViewPort.DxOffset and ViewPort.DyOffset the 
  2196. upper left corner of the ViewPort will be positioned at exactly the same
  2197. location as the View. Different values (larger than zero) will place your
  2198. ViewPort somewhere in the middle of the screen.
  2199.        
  2200. ViewPort.DWidth and ViewPort.DHeight set the size of the ViewPort. When 
  2201. setting these variables you must remember which resultion you selected.
  2202. If you selected 640 pixels horizontal resolution (ViewPort.mode = hires),
  2203. you must specify a ViewPort.DWidth of 640 (instead of 320 normal mode).
  2204. This also applies to ViewPort.Mode = LACE (interlace mode), which must
  2205. have a ViewPort.DHeight of 400 instead of 200 (PAL 51 instead of 256).
  2206.        
  2207.                             PAGE 317
  2208.        
  2209. -----------------------------------------------------------------------------                                                               
  2210.        
  2211. A color map (or palette) is required for the color resolution. Since the 
  2212. different color entries require memory, we must assign them.
  2213.        
  2214.        ColorMap = (struct ColorMap *) GetColorMap
  2215.        (Number_of_Colors)
  2216.        
  2217. sets up an entire structure called the ColorMap structure. This structure 
  2218. stores the pointers to the color memory and the number of available colors
  2219. for the ViewPort.
  2220.        
  2221. After you initialise the ColorMap you must make it available to the 
  2222. ViewPort. You can send a pointer for the color map to the ViewPort like
  2223. this:
  2224.        
  2225.        ViewPort.ColorMap = ColorMap
  2226.        
  2227. or make a direct call like this:
  2228.        
  2229.        ViewPort.ColorMap = (struct ColorMap *)GetColorMap(Number_of_colors)
  2230.        
  2231. It is important that you use the Cast ('...(struct ColorMap*)') to 
  2232. prevent warnings (pointers do not point to same object).
  2233.        
  2234. You can determine the returned values of the function GetColorMap (and
  2235. all other functions) before the program sets them:
  2236.        
  2237.        extern struct ColorMap *GetColorMap()
  2238.        
  2239.        .....
  2240.        
  2241.        main()
  2242.        
  2243. Now the compiler will no display the warning messages when you call 
  2244. ViewPort.ColorMap = GetColorMap(Number_of_Colors).
  2245.        
  2246. To prevent the ViewPort structure from containing any random values that 
  2247. would confuse the system, we also have an initialise command:
  2248.        
  2249.        InitVPort(&ViewPort)
  2250.        
  2251. You should always use this command before writing any values to the 
  2252. ViewPort or using the ViewPort.
  2253.        
  2254. Before we can make use of the BitMap we have to make a connection between 
  2255. the ViewPort and the View:
  2256.        
  2257.        View.ViewPort = &ViewPort
  2258.                      
  2259.                             PAGE 318
  2260.        
  2261. -----------------------------------------------------------------------------
  2262.        
  2263. 9.4 The Worker: the BIT-MAP
  2264. ===========================
  2265.        
  2266. At some time and in some place our graphic must be entered into memory.
  2267. The bitmap controls both when and where this will occur. Then this 
  2268. information is divided among different bitplanes. The number of bitplanes
  2269. sets how many colours are located in the ViewPort and displayed by the 
  2270. BitMap. The more bitplanes there are the more colors. The actula number 
  2271. of colours is calculated below:
  2272.        
  2273.        Number_of_Colors = 2^Number_of_bitplanes
  2274.        
  2275. This calculation is based on the way the planes are graphically layered
  2276. on top of each other in the display (in memory they are actually stored
  2277. one after another).
  2278.        
  2279. Each pixel is represented by one bit in every bitplane. The combination
  2280. of all set an unset bits in a pixel in all the bitplanes determines the 
  2281. number of the colour register (See chapter 14). The pixel is then 
  2282. dispayed in that colour.
  2283.        
  2284. The AllocRaster function (a subset of the AllocMem function) allocates
  2285. memory (bytes) for the individual bitplanes. This function also makes 
  2286. sure that the assigned memory area begins at an even word address. This
  2287. is necessary since the system can only access even word addresses.
  2288.        
  2289. You use BitMap.Planes[i] = AllocRaster(width,Height) to assign the 
  2290. required memory for a bit-plane of the bitmap.
  2291.        
  2292.                             PAGE 319
  2293.        
  2294. -----------------------------------------------------------------------------
  2295.        
  2296. Width sets the width in pixels and height sets the height in rows. You must 
  2297. make sure that the pointer BitMap.Planes[i] never equals zero. If this 
  2298. happens, you will be unable to reserve enough memory. (The same thing can
  2299. happen when you use a value of zero with OpenLibrary or GetColorMap). Most
  2300. of the time this results in insufficient memory problems. When this 
  2301. happens, try to have your program be the only one active (other than the
  2302. CLI or WorkBench) in your Amiga. Test the return values of the functions
  2303. and have them print an attention message if they receive a value of zero.
  2304. This will let all users know which memory areas cannot be used. For 
  2305. example:
  2306.        
  2307.        printf ("No more memort available for ColorMap/n");
  2308.        exit(0);
  2309.        
  2310. Now back to the number of bitplanes. The system provides us with eight 
  2311. BitMap.Planes[1...8] pointers. At the moment (Kickstart 1.2, Amiga 2000) 
  2312. only a maximum of six of these can be used. Later, by expanding the system,
  2313. it may be possible to use all of them.
  2314.        
  2315. Six bitplanes can provide up to 2^6 = 64 displayed colors. There are 
  2316. actually only 32 possible colours based on the pixel-bits (the Amiga
  2317. 2000/1000/500 only has 32 colour registers).
  2318.        
  2319. We only require that five bitplanes have 32 colours. The sixth bitplane is
  2320. used with HAM and Halfbrite modes. (see chapter 17.)
  2321.        
  2322. There is still another limitation to discuss. You can only work with 4 
  2323. bitplanes in hi-res mode or 640 pixel horizontal resolution. The reason for
  2324. this is that we have more data to display on the screen. The four 
  2325. bitplanes use up the limited time the Amiga has available to display all
  2326. of this data.
  2327.        
  2328. Before we continue with the bitmaps we will show you how to initialise
  2329. the bitplanes (or memory).
  2330.        
  2331. Since we cannot guarantee that the memory is clear, we must clear it 
  2332. ourselves (otherwise we many have a mess on the screen).
  2333.        
  2334. BltClear(BitMap.Planes[i],Number_of_Bytes,Flags) is used to clear 
  2335. memory. To calculate the number of bytes to clear use the following:
  2336.        
  2337.        Number_of_Bytes = Width*Height/8
  2338.        
  2339. The macro RASSIZE(Width,Height) calculates the same value (For the 
  2340. parameter flags please see Appendix B. Normally flags are set equal to 
  2341. zero).
  2342.        
  2343.                             PAGE 320
  2344.        
  2345. -----------------------------------------------------------------------------
  2346.        
  2347. The memory area information that you receive from AllocRaster is
  2348. distributed in an individual bitplane row like this:
  2349.        
  2350. The bytes '0 to width/8-1' represent the memory for the first row of the 
  2351. bitplane. The bytes 'width/8 to 2*width/8-1' represent the second row and
  2352. this pattern continues to the last byte.
  2353.        
  2354. Now that we have closely studied the bitplanes, we will move to the 
  2355. bitmap (the bitplane factory).
  2356.        
  2357. We set the size of the bitmap and the depth (number of bitplanes) in the 
  2358. bitmap structure. The size of the BitMap and of the ViewPort can be 
  2359. different.
  2360.        
  2361. The only thing you have to remember is that the bitmap must be within the
  2362. 1024*1024 row/pixel limit. You initialise the bitmap with :
  2363.        
  2364.        InitBitMap(&BitMap,Depth,Width,Height);
  2365.        
  2366.                             PAGE 321
  2367.        
  2368. -----------------------------------------------------------------------------
  2369.        
  2370. 9.5 THE MESSANGER: RasInfo.
  2371. ===========================
  2372.        
  2373. The BitMap and the ViewPort are still isolated from each other. We can 
  2374. connect them by using the RasInfo structure. This structure isnt 
  2375. established with an initialise procedure. You must program this structure,
  2376. element by element, by writing the necessary values into it.
  2377.        
  2378. The actual connetion between the ViewPort and the bitmap to the RasInfo 
  2379. structure is made as follows:
  2380.        
  2381.        ViewPort.RasInfo = &RasInfo
  2382.        RasInfo.BitMap   = &BitMap
  2383.        
  2384. The bitmap pointer of the RasInfo stucture (Raster information) is the 
  2385. only common element. The only remaining variables to be initialised are the
  2386. RxOffset and the RyOffset. These specify the pixel coordinates for the 
  2387. upper left corner of the ViewPorts and are normally initialised to zero.
  2388.        
  2389. The last RasInfo variable, the RasInfo.Next pointer, is used only for 
  2390. special display modes (see chapter 17) and is normally set to zero.
  2391.        
  2392.                             PAGE 322
  2393.        
  2394. -----------------------------------------------------------------------------
  2395.        
  2396. 9.6: The Laborer: THE RASTPORT.
  2397. ===============================
  2398.        
  2399. We can compare the RastPort, which means the RastPort structure, to a heavy
  2400. laborer. We process almost all of the graphic output through the RastPort 
  2401. because it contains the actual color of the pixels, the drawing mode (See
  2402. chapter 11) and much more (See appendix A).
  2403.        
  2404. InitRastPort(&RastPort) initialises the RastPort. This initialisation sets
  2405. up default values that can be changed later by using the proper commands.
  2406.        
  2407. After initialising the RastPort, you need to supply the address of the 
  2408. BitMap where your graphic commands will become visible:
  2409.        
  2410.        RastPort.BitMap = &BitMap
  2411.        
  2412. Now we have initialised all the required structures and linked them 
  2413. together (The RastPort does not require a link to the ViewPOrt because 
  2414. it only provides information for the graphic commands).
  2415.        
  2416. Until now, nothing has appeared on the screen. Finally, we can start
  2417. creating something that will be shown on the screen.
  2418.        
  2419. The reason why there hasnt been anything shown on the screen is because the
  2420. Copper list created by special programs and used by the Copper coprocessor 
  2421. doesn't exist yet. The hardware registers are espcially affected by the 
  2422. copper list which is required to control the graphic display. See appendix
  2423. C, register bltcon/1, bplcon0/1/2 etc...
  2424.        
  2425. The copper list is created by using MakeVPort(&View,&ViewPort) and 
  2426. MrgCop(&View) which use the data initialised in View, ViewPort etc...
  2427.        
  2428. First we use MakeVPort to create an intermediate Copper list for every 
  2429. ViewPort (There can be more than one ViewPort in a View but you must make
  2430. sure that a difference of at least on pixel row exists between the 
  2431. ViewPorts when they overlap). The Copper itself is unable to do anything
  2432. with these intermediate lists. Once all the ViewPort Copperlists are 
  2433. created, we use MrgCop to make a final copperlist that the Copper is able
  2434. to use. To make this list active, use LoadView(&View).
  2435.        
  2436. Finally, the copper works on the Copper list and you can see the results
  2437. on the screen. Before activating the copper list you should save the 
  2438. existing Copper list in a variable (oldview= GfxBase->ActiView). The 
  2439. GfxBase structure helps us do this because it always contains a pointer to
  2440. the actual View.
  2441.        
  2442.                             PAGE 323
  2443.        
  2444. -----------------------------------------------------------------------------
  2445.        
  2446. If, just one time, you forget to save your old view by calling 
  2447. LoadView(oldview) before running your program, you will be lost in the 
  2448. Amiga jungle. Since we start most programs from the CLI or Workbench, you
  2449. wont be able to return to the WorkBench screen where the CLI window is
  2450. located.
  2451.        
  2452. The following illustration shows how the View, ViewPort, RastPort, bitmap,
  2453. RasInfo etc.. are linked together:
  2454.        
  2455.       __________
  2456.      | View     |
  2457.      |----------|      __________  
  2458.      | ViewPort |---->| ViewPort |
  2459.      |__________|     |----------|
  2460.               | Next     |
  2461.               |----------|      ____________
  2462.               | ColorMap |---->| ColorMap   |
  2463.       __________      |----------|     |------------|      ___________
  2464.      | RasInfo  |<----| RasInfo  |     | Color Table|---->|Color0     |    
  2465.      |----------|     |__________|     |____________|     |-----------|
  2466.      | Next     |                      |Color 1    |
  2467.      |----------|      ___________      ____________      |-----------|
  2468.      | BitMap   |---->| Bitmap    |<---| RastPort   |     | ......... |
  2469.      |__________|     |-----------|    |------------|     |-----------|
  2470.               | Planes[x] |    |   (TmpRas) |     |Color 32   |
  2471.               |___________|    |------------|     |___________|
  2472.                         |  (Areainfo)|
  2473.               / | \           |------------|
  2474.                  /  |  \       |  (Gelsinfo)|
  2475.                 /   |   \      |____________|
  2476.        
  2477.               To the six bitplanes.
  2478.  
  2479.                             PAGE 324
  2480.        
  2481. -----------------------------------------------------------------------------
  2482.       
  2483. 9.7 FINISH THE DAY.
  2484. ===================
  2485.        
  2486. In our programs, "finish the day" means we still have more work to do.First
  2487. we have to return the reserved memory back to the system. Then we have to 
  2488. close all opened libraries sing CloseLibrary(base pointer). The base pointer
  2489. for the graphics library must be GfxBase.
  2490.        
  2491. When you are returning memory, you must remember that the Copper list you 
  2492. created with MakeVPort and MrgCop uses memory also.
  2493.        
  2494. To release the ViewPort intermediate lists, use FreeVPortCopLists(&View
  2495. Port). Then use FreeCprList(View LOFCprList) and FreeCprList (View 
  2496. SHFCprList) to release the actual Copper list (See Appendix A for View/ 
  2497. LOF/SHFCprList).
  2498.        
  2499. FreeRaster (Bitmap Planes [i]), Width, Height) is used to release the 
  2500. memory for every bit-plane used).
  2501.        
  2502. To release the reserved memory for the color map, use FreeColorMap
  2503. (&ColorMap) and FreeColorMap(ViewPort.ColorMap).
  2504.        
  2505.                             PAGE 325
  2506.        
  2507. -----------------------------------------------------------------------------
  2508.  
  2509.                      CHAPTER 10 : LINES AND PIXELS.
  2510.                      ==============================
  2511.        
  2512. Now we can begin our discussion of our first graphic commands. The smallest
  2513. element in all computer graphics is the pixel.
  2514.        
  2515.               -----------------------------------------------
  2516.        
  2517. 10.1 PIXELS SET WITH WRITEPIXEL.
  2518. ================================
  2519.        
  2520. You can set a single pixel in the bitmap with the WritePixel(&RastPort, x,y)
  2521. function. The RastPort, which is one of the required parameters, contains 
  2522. the colour used to write the pixel to the bitmap.
  2523.        
  2524. The X and Y parameters specify the two-dimensional coordinate for the 
  2525. pixel. Please remember that the coordinates begin from the upper-left 
  2526. corner. The Y coordinate value increases as you go move towards the 
  2527. bottom of the screen. The X coordinate increases as you move towards the 
  2528. right side of the screen.
  2529.        
  2530.        
  2531.        (0,0)                                   (320/640,0)
  2532.        ___________________________________________________>
  2533.        |                                         x
  2534.        |
  2535.        |
  2536.        |
  2537.        |
  2538.        |
  2539.        |
  2540.        |
  2541.        |
  2542.        |
  2543.        |
  2544.        |
  2545.        |
  2546.        | (0,200/400) y
  2547.       \/
  2548.        
  2549. The following program opens a View, ViewPort etc. It uses WritePixel
  2550. to create a string of pixels. We set each pixel in the string to a 
  2551. different colour. After the drawing is complete, we rotate the contents of
  2552. the colour registers with the ColorMap function (see Chapter 14). This 
  2553. creates the familiar color cyclin effect used by Deluxe Paint.
  2554.        
  2555.                             PAGE 327
  2556.        
  2557. -----------------------------------------------------------------------------
  2558.        
  2559.        /*********************************************/
  2560.        /*                                           */
  2561.        /*               strings.c                   */
  2562.        /*                                           */
  2563.        /* This program uses WritePixel() to create  */
  2564.        /* a string that uses colour cycling         */
  2565.        /* animation.                                */
  2566.        /*                                           */
  2567.        /* Compile With : Lattice V5.                */
  2568.        /*********************************************/
  2569.        
  2570.        #include "exec/types.h"
  2571.        #include "exec/memory.h"
  2572.        #include "exec/devices.h"
  2573.        #include "graphics/gfx.h"
  2574.        #include "graphics/gfxbase.h"
  2575.        #include "graphics/gfxmacros.h"
  2576.        #include "graphics/text.h"
  2577.        #include "graphics/view.h"
  2578.        #include "graphics/clip.h"
  2579.        #include "graphics/copper.h"
  2580.        #include "graphics/gels.h"
  2581.        #include "graphics/regions.h"
  2582.        #include "hardware/blit.h"
  2583.        #include "devices/keymap.h"
  2584.        
  2585.        #define Width 320
  2586.        #define Height 200
  2587.        #define Depth 4
  2588.        #define MODES 0              /* REsolution mode */
  2589.        
  2590.        struct GfxBase *GfxBase;
  2591.        
  2592.        struct View View; /* structures for our display */
  2593.        struct ViewPort ViewPort;
  2594.        struct RasInfo RasInfo;
  2595.        struct BitMap BitMap;
  2596.        struct RastPort RastPort;
  2597.        struct View *oldView;
  2598.        
  2599.        int i,x,y,factor;
  2600.        
  2601.        UWORD color = 0;              /* Colour counter */
  2602.        
  2603.        USHORT Colors[16] = {
  2604.                             0x000, 0x00f, 0x0f0, 0xf00,
  2605.                             0x0ff, 0xff0, 0xf0f, 0xc34,
  2606.                             0x646, 0x782, 0xd23, 0x5a9,
  2607.                             0x560, 0xacf, 0xedf, 0xa09
  2608.                            }; 
  2609.                                    /* Initial color table */
  2610.        
  2611.        char *LeftMouse = (char *)0xbfe001;
  2612.        
  2613.        VOID Color();              /* Forward Declaration */
  2614.        VOID Color_Cycle();
  2615.        
  2616.                             PAGE 328
  2617.        
  2618. ---------------------------------------------------------------------------
  2619.        
  2620.        /*******************************************/
  2621.        /* Here We Go !                            */
  2622.        /*******************************************/
  2623.        
  2624.        main()
  2625.            {
  2626.                if((GfxBase = (struct GfxBase *)
  2627.                   OpenLibrary("graphics.library",0))==NULL)
  2628.                       {
  2629.                           printf("No graphics library !!!!");
  2630.                           exit(0);
  2631.                       }
  2632.                oldView = GfxBase->ActiView; /* Save old View */
  2633.                
  2634.                InitView(&View);             /* Initialise View*/
  2635.                InitVPort(&ViewPort);        /* Initialise ViewPort */
  2636.            
  2637.                View.ViewPort = &ViewPort;   /* Link view and viewport */
  2638.        
  2639.                View.Modes = MODES;          /* Set viewmodes */
  2640.            
  2641.                ViewPort.DWidth = Width;     /* Set viewport parameters */
  2642.                ViewPort.DHeight= Height;    
  2643.                ViewPort.RasInfo= &RasInfo;
  2644.                ViewPort.Modes  = MODES;
  2645.                ViewPort.ColorMap = (struct ColorMap *)GetColorMap(16);
  2646.                if(ViewPort.ColorMap == 0) goto cleanup1;  
  2647.                                                    /* Set colour map */
  2648.        
  2649.                RasInfo.Next =NULL;              /* Link ViewPort-Bitmap */
  2650.                RasInfo.RxOffset = 0;            /*   thru RasInfo     */
  2651.                RasInfo.RyOffset = 0;              
  2652.                RasInfo.BitMap   = &BitMap;
  2653.        
  2654.                InitBitMap( &BitMap, Depth, Width, Height); 
  2655.                                                /* Initialise BitMap */
  2656.            
  2657.                for (i=0; i<depth; i++)
  2658.                    {
  2659.                        BitMap.Planes[i] = (PLANEPTR) 
  2660.                            AllocRaster(Width,Height);
  2661.                        if (BitMap.Planes[i] == 0)
  2662.                            {
  2663.                                printf("No memory for bitplanes \n");
  2664.                                goto cleanup1;
  2665.                            }
  2666.                        else 
  2667.                            BltClear(BitMap.Planes[i],
  2668.                                RASSIZE(Width, Height),0);              
  2669.                                           /* Erase Bitplanes *
  2670.                    }
  2671.        
  2672.                             PAGE 329
  2673.        
  2674. -----------------------------------------------------------------------------
  2675.         
  2676.             InitRastPort(&RastPort) ; /* Initialise Rastport */
  2677.             RastPort.BitMap = &BitMap; /* Link RastPort BitMap
  2678.             
  2679.             LoadRGB4(&ViewPort,&Colors[0],16);
  2680.                         /* Write colors to ViewPort   */
  2681.                         /* ColorMap. Follow this with */
  2682.                         /* MakeVPort(), MrCop() and   */
  2683.                         /*    LoadView()              */
  2684.                         /* (Intuition:RemakeDisplay())*/
  2685.             MakeVPort(&View, &ViewPort);
  2686.             MrgCop(&View);
  2687.             LoadView(&View);
  2688.         
  2689.             color = 1;                       /* Color Animation */
  2690.         
  2691.             x=0; 
  2692.             y=0; 
  2693.             factor = 1;
  2694.             
  2695.             while (y < height-1)
  2696.                 {
  2697.                     SetAPen(&RastPort,color);
  2698.                     WritePixel(&RastPort,x,y);
  2699.             
  2700.                     x+= (factor);
  2701.                     if ((x>width-1) || (x==0))
  2702.                         {
  2703.                             for(i=0; i<7; i++)
  2704.                                 {
  2705.                                     Color();
  2706.                                     SetAPen(&RastPort,color);
  2707.                                     WritePixel(&RastPort,x,y+1);
  2708.                                 }
  2709.                             factor *= -1;
  2710.                             y +=6;
  2711.                         }
  2712.                     Color();
  2713.                 }
  2714.         
  2715.             while ((*LeftMouse & 0x40) == 0x40)
  2716.                 {
  2717.                     Color_Cycle();
  2718.                 }
  2719.         
  2720.             FreeColorMap(ViewPort.ColorMap);   /* Set   */
  2721.             FreeVPortCopLists(&ViewPort);      /* all   */
  2722.             FreeCprList(View.LOFCprList);      /* free  */
  2723.             FreeCprList(View.SHFCprList);
  2724.         
  2725.         cleanup1: for(i=0; i<depth; i++)
  2726.                     {
  2727.                         if (BitMap.Planes[i] != NULL)
  2728.                         FreeRaster (BitMap.Planes[i],Width,Height);
  2729.                     }
  2730.             LoadView(oldView);
  2731.             CloseLibrary(GfxBase);
  2732.             return(0);
  2733.         }
  2734.         
  2735.                                 PAGE 330
  2736.         
  2737. ----------------------------------------------------------------------------
  2738.         
  2739.         /************************************************/
  2740.         /*                                              */
  2741.         /* This routine takes care of incrementing the  */
  2742.         /* color counter while drawing.                 */
  2743.         /*----------------------------------------------*/
  2744.         /* Entry Parameters : None                      */
  2745.         /*----------------------------------------------*/
  2746.         /* Returned Values : None                       */
  2747.         /*----------------------------------------------*/
  2748.         
  2749.         VOID Color()
  2750.             {
  2751.                 color++;
  2752.                 color&=15;
  2753.                 if (color==0) color = 1;
  2754.             }
  2755.         
  2756.         /************************************************/
  2757.         /*                                              */
  2758.         /* Thsi routine takes care of rotating the      */
  2759.         /* colours of the ViewPort ColorMap.            */
  2760.         /*----------------------------------------------*/
  2761.         /* Entry Parameters : None                      */
  2762.         /*----------------------------------------------*/
  2763.         /* Returned Values : None                       */
  2764.         /************************************************/
  2765.         
  2766.         VOID Color_Cycle()
  2767.             {
  2768.                 UWORD i,help;
  2769.                 static UWORD Cols[16];
  2770.             
  2771.                 Cols[0] = Colors[0];   /* Background Color Remains */
  2772.             
  2773.                 help = GetRGB4 (ViewPort.ColorMap,15);
  2774.                 for (i=2; i<16; i++)
  2775.                     Cols[i] = GetRGB4(ViewPort.ColorMap,i-1);
  2776.                 Cols[1] = help;
  2777.                                     /* Shuffle */
  2778.                 LoadRGB4(&ViewPort,&Cols[0],16);
  2779.                 MakeVPort (&View,&ViewPort);   /* Important !!! */
  2780.                 MrgCop(&View);
  2781.                 LoadView(&View);
  2782.             }
  2783.         
  2784.                                 PAGE 331
  2785.         
  2786. --------------------------------------------------------------------------
  2787.  
  2788. 10.2 DRAWING LINES WITH MOVE AND DRAW.
  2789.         
  2790. Naturally, the Amiga can also draw lines. What is remrakable about this 
  2791. capability is that the 68000CPU is hardly used for this function. 
  2792. Instead, the blitter, (one of the Amigas special coprocessors) executes 
  2793. this function independantly.
  2794.         
  2795. First we have to set the starting coordinates. Drawing lines in C 
  2796. language differes from drawing lines in BASIC because C requires two 
  2797. functions instead of only one.
  2798.         
  2799. The MOVE function sets the actual graphic position (graphic cursor) to the
  2800. specified coordinates:
  2801.         
  2802.         Move (&RastPort,x,y)
  2803.         
  2804. At the same time, there coordinates are stored in the reference RastPort
  2805. (RastPort.cp_x and RastPort.cp_y).
  2806.         
  2807. The Draw(&RastPort,x,y) function draws a line to the specified coordinates.
  2808. These coodrinates automatically become the new graphic cursor positions.
  2809. The draw (&RastPort,x,y) function draws a line to the specified coordinates.
  2810.  The next Draw function (without any moves in between) draws from the last
  2811. pixel that was drawn to the pixel coordinates specified by the new Draw 
  2812. function.
  2813.         
  2814. The following program demonstrates the powerful Amiga capability:
  2815.         
  2816.         
  2817.         /*******************************************************/
  2818.         /*                        Quix.c                       */
  2819.         /*                                                     */
  2820.         /* This program demonstrates the hidden speed of the   */
  2821.         /* Amiga, especially when drawing lines.               */
  2822.         /*                                                     */
  2823.         /* Compiled with LAttice V5                            */
  2824.         /*                                                     */
  2825.         /* (c) Buno Jenrich                                    */
  2826.         /*******************************************************/
  2827.         
  2828.         #include "exec/types.h"
  2829.         #include "graphics/gfx.h"
  2830.         #include "graphics/copper.h"
  2831.         #include "graphics/view.h"
  2832.         #include "graphics/gels.h"
  2833.         #include "graphics/regions.h"
  2834.         #include "graphics/clip.h"
  2835.         #include "graphics/text.h"
  2836.         #include "graphics/gfxbase.h"
  2837.         #include "graphics/rastport.h"
  2838.         
  2839.                                 PAGE 332
  2840.         
  2841. ----------------------------------------------------------------------------
  2842.         
  2843.         #include "hardware/blit.i"
  2844.         
  2845.         #define DEPTH 2                        /* 2 bitplanes */
  2846.         #define WIDTH 320                      /* 320 * 200 pixels. */
  2847.         #define HEIGHT 200
  2848.         
  2849.         #define MAX_X WIDTH-2   /* Do not exceed borders */
  2850.         #define MAX_Y HEIGHT-2  /* Left, Right, Bottom */
  2851.         #define MIN_X 1
  2852.         #define MIN_Y 10        /* Do not write over text */
  2853.         
  2854.         #define NOT_ENOUGH_MEMORY -1000
  2855.         #define MAX_LINES 30    /* Maximium 30 lines
  2856.             
  2857.         struct View View;        /* Our own structures */
  2858.         struct ViewPort ViewPort;
  2859.         struct RasInfo RasInfo; struct ColorMap *ColorMap
  2860.         struct BitMap BitMap;
  2861.         struct RastPort RastPort;
  2862.         
  2863.         SHORT i,j,length;
  2864.         
  2865.         struct GfxBase *GfxBase;
  2866.         struct View *oldView;   /* here we save the old view */
  2867.         
  2868.         USHORT colortable[] = {0x000, 0xf00, 0x00f, 0x0f0);
  2869.                                 /* our own colour palette */
  2870.         
  2871.         char *QuixString = "Quix - Line *** (C) BHJ";
  2872.         char *LeftMouse;        /* For CIA address */
  2873.         
  2874.         VOID draw();            /* Forward delcaration */
  2875.         VOID FreeMemory();
  2876.         
  2877.         /**************************************************/
  2878.         /* Here we go !                                   */
  2879.         /**************************************************/
  2880.         
  2881.         main()
  2882.             {
  2883.                 if((GfxBase = (struct GfxBase *)
  2884.                     OpenLibrary("graphics.library",0))==NULL)
  2885.                         exit(1);
  2886.         
  2887.                 oldview = GfxBase->ActiView;   /* Save old View */
  2888.         
  2889.                 InitView(&View);        /* initialise view and viewport */
  2890.                 InitVPort(&ViewPort);
  2891.                 View.ViewPort = &ViewPort; /* link them together */
  2892.         
  2893.                 InitBitMap(&BitMap, DEPTH, WIDTH, HEIGHT);
  2894.                                             /* initialise bitmap */
  2895.         
  2896.                 InitRastPort(&RastPort);    /* RastPort */
  2897.         
  2898.                                PAGE 333
  2899.         
  2900. ---------------------------------------------------------------------------
  2901.         
  2902.                 RastPort.BitMap = &BitMap;    /* RastPort ->BitMap
  2903.         
  2904.                 RasInfo.BitMap = &BitMap;        /* RasInfo for BitMap */
  2905.                 RasInfo.RxOffset = 0;
  2906.                 RasInfo.RyOffset = 0;
  2907.                 RasInfo.Next = NULL;
  2908.             
  2909.                 ViewPort.RasInfo = &RasInfo;  /* ViewPort -> RasInfo */
  2910.             
  2911.                 ViewPort.DWidth = WIDTH;      /* How big is ViewPort ? */
  2912.                 ViewPort.DHeight = HEIGHT;    
  2913.             
  2914.                 ViewPort.ColorMap = (struct ColorMap *)GetColorMap(4);
  2915.                                         /* ViewPort's ColorMap */
  2916.             
  2917.                 LoadRGB4 (&ViewPort,&colortable[0],4);
  2918.                                         /* Load ColorMap with Colors. */
  2919.                 for(i=0; i<DEPTH; i++);
  2920.                     {
  2921.                         if (BitMap.Planes[i] = (PLANPTR)
  2922.                           AllocRaster(WIDTH, HEIGHT)) == NULL)   
  2923.                                Exit(NOT_ENOUGH_MEMORY);
  2924.                                 /* Reserve memory for BitPlanes */
  2925.                         BltClear((UBYTE *)BitMap.Planes[i],
  2926.                             RASSIZE(WIDTH,HEIGHT),0);
  2927.                                 /* Erase BitPlane memory */
  2928.                     }
  2929.             
  2930.                 MakeVPort(&View,&ViewPort);  /* Copper list for ViewPort */
  2931.             
  2932.                 MrgCop(&View);   /* "size" CopperList: for view */
  2933.             
  2934.                 LoadView(&View); /* switch new display on */
  2935.             
  2936.                 LeftMouse = (char *)Oxbfe001;
  2937.                                  /* CIA address for I/O ports */
  2938.                                  /* are used for Left         */
  2939.                                  /* Mouse Button              */
  2940.         
  2941.                 draw();        /* Your routine */
  2942.         
  2943.                 LoadView(oldview);   /* Workbench display on */
  2944.                 FreeMemory();        /* Return everything */
  2945.                 return(0);
  2946.             }
  2947.         
  2948.         /**********************************************************/
  2949.         /*                                                        */
  2950.         /* This function takes care of drawing the lines and      */
  2951.         /* reading the left mouse button.                         */
  2952.         /*--------------------------------------------------------*/
  2953.         /* Entry parameters : None                                */
  2954.         /*--------------------------------------------------------*/
  2955.         /* Returned values  : None                                */
  2956.         /*--------------------------------------------------------*/
  2957.         
  2958.                                 PAGE 334
  2959.         
  2960. ---------------------------------------------------------------------------
  2961.         
  2962.         VOID draw()
  2963.             {
  2964.                 static SHORT i,
  2965.                 new = 0,
  2966.                 old = 0,
  2967.                 full = FALSE,
  2968.                 min, temp,
  2969.                 delay =1999,
  2970.                 direction = 1,
  2971.                 k = 0;
  2972.             
  2973.             struct {                /* coordinates for one line */
  2974.                     int x1[MAX_LINES],
  2975.                         x2[MAX_LINES],
  2976.                         y1[MAX_LINES],
  2977.                         y2[MAX_LINES];
  2978.                     } line;
  2979.             
  2980.             static int veloc[4] = {-4,5,3,-7};
  2981.                     /* what is added to the coordinate ? */
  2982.             
  2983.             static int start[4] = {110,25,160,74};
  2984.                     /* Where is the first line drawn ? */
  2985.             
  2986.             static int max[4] = {MAX_X, MAX_Y, MAX_X, MAX_Y};
  2987.                     /* Allowed maximum value of coordinates */
  2988.             SetDrMd(&RastPort,JAM1);
  2989.             SetAPen(&RastPort,3);   /* Drawing Colors = Green */
  2990.             
  2991.             Length = WIDTH/2-TextLength(&RastPort, QuixString,
  2992.                     strlen(QuixString))/2;
  2993.                                     /* calculate central position */
  2994.                     Move(&RastPort,Length,RastPort,TxBaseline);
  2995.                                     /* position graphic cursor */
  2996.                 
  2997.                     Text(&RastPort, QuixString, strlen(QuixString));
  2998.                                     /* display text            */
  2999.                         
  3000.                     SetAPen(&RastPort,1);   /* drawing colour = red */
  3001.             
  3002.                     Move(&RastPort,0,9);        /* draw frame */
  3003.                     Draw(&RastPort,WIDTH-1,9);
  3004.                     Draw(&RastPort,WIDTH-1, HEIGHT-1);
  3005.                     Draw(&RastPort,0,HEIGHT-1);
  3006.                     Draw(&RastPort,0,9);
  3007.             
  3008.             
  3009.                     while ((*LeftMouse & 0x40) == 0x40) /* Mouse button ? */
  3010.                         {
  3011.                             for(i=0; i<4; i++) /* calc new line coords */
  3012.                                 {
  3013.                                     temp = start[i] + veloc[i];
  3014.                                         /* Exit value + "speed" */
  3015.                                     if(temp>=max[i])
  3016.                                         /* exceeds upper limit ? */
  3017.                                     {
  3018.         
  3019.                                 PAGE 335
  3020.         
  3021. ---------------------------------------------------------------------------
  3022.         
  3023.                                        temp=max[i]*2 - start[i] - veloc[i];
  3024.                                        veloc[i] = -veloc[i]
  3025.                                     }
  3026.                                 if(i==1 | i==3) min = MIN_Y;
  3027.                                 /* Check Y coords */
  3028.                                 else min = MIN_X;
  3029.                                 
  3030.                                 if (temp<min)
  3031.                                 {
  3032.                                    /* exceeds lower border ?*/
  3033.                                   if (tmp<0) temp = -temp;
  3034.                                   else temp = min;
  3035.                                   veloc[i] = -veloc[i];
  3036.                                         }
  3037.                                     start[i] = temp;
  3038.                                 }
  3039.                          
  3040.         if (full == TRUE)
  3041.             {
  3042.                                         /* Erase last line */
  3043.                 SetAPen(&RastPort,0);
  3044.                 Move(&RastPort,line.x1[old], line.x2[old]);
  3045.                 Draw(&RastPort,line.x2[old], line.y2[old]);
  3046.             
  3047.                 old++;
  3048.                 old% = MAX_LINES;
  3049.             }
  3050.             
  3051.         line.x1[new]  = start[0];                /* set new line */
  3052.         line.y1[new]  = start[1];                /* coordinates  */
  3053.         line.x2[new]  = start[2];                      
  3054.         line.y2[new]  = start[3];
  3055.         
  3056.         if(new == MAX_LINES-1) full = TRUE;
  3057.                             /* MAX_LINES drawn ? */
  3058.             
  3059.         SetAPen(&RastPort,2);        /* Drawing colour = blue */        
  3060.         Move(&RastPort,line.x1[new],line.y1[new]);
  3061.         Draw(&RastPort,line.x2[new],line.y2[new]);
  3062.                                     /* Draw new line */
  3063.         
  3064.         new++;
  3065.         new%= MAX_LINES;
  3066.         
  3067.         if(delay != 0)
  3068.             {
  3069.                 for(i=0; i<delay; i++);
  3070.                                     /* wait a bit *
  3071.                 delay += direction;
  3072.         
  3073.                                 PAGE 336
  3074.         
  3075. --------------------------------------------------------------------------
  3076.         
  3077.                     if (delay = 2000) direction = -1;
  3078.                 }
  3079.             else
  3080.                 {
  3081.                     k++;
  3082.                   if(k== 1000) /* 1000 times 'full power' */
  3083.                     {
  3084.                         direction = 1;
  3085.                         delay += direction;
  3086.                         k = ;
  3087.                     }
  3088.                   }
  3089.                }
  3090.             }
  3091.         }
  3092.         
  3093.         /*****************************************************/
  3094.         /* This function returns allocated memory for bitmaps*/
  3095.         /* copper lists etc...                               */
  3096.         /*---------------------------------------------------*/
  3097.         /* Entry parameters : None                           */
  3098.         /*---------------------------------------------------*/
  3099.         /* Returned values  : None                           */
  3100.         /*---------------------------------------------------*/
  3101.         
  3102.         VOID FreeMemory()
  3103.             {
  3104.                 for(i=0; i<DEPTH; i++)
  3105.                     FreeRaster(BitMap.Planes[i], WIDTH, HEIGHT);
  3106.                                                 /* Return bitplane memory */
  3107.                     FreeColorMap(ViewPort.ColorMap);
  3108.                                     /* Release ColorMap memory that was */
  3109.                                     /* reserved with ColorMap()         */
  3110.         
  3111.                     FreeVPortCopLists(&ViewPort);
  3112.                                     /* Free memory for                  */
  3113.                                     /* ViewPort CopperList              */
  3114.                                     /* from MakeVPort()                 */
  3115.         
  3116.                     FreeCprList(View.LOFCprList);
  3117.                     FreeCprList(View.SHFCprList);   
  3118.                                      /* View Coppelist */
  3119.                 
  3120.                     CloseLibrary(GfxBase);
  3121.                                      /* Close Library */
  3122.             }
  3123.         
  3124. We have two additional tips for you. It is possible to exit most of our
  3125. programs by using a mouse button. This is achieved by constantly checking
  3126. the hardware registers. You would probably find this quite useful in your
  3127. own programs.
  3128.         
  3129. If you dont like the line pattern we used, you can create a new pattern 
  3130. with SetDrPt(&RastPort, Pattern). The 16 bit word pattern contains the 
  3131. actual pixel pattern for the line. (we set Pattern = 0xffff which draws
  3132. a full line).
  3133.         
  3134.                                 PAGE 337
  3135.         
  3136. ----------------------------------------------------------------------------
  3137.        
  3138. 11. COLOR: DRAWING PENS.
  3139.         
  3140. After the two previous programs were up and running, you probably 
  3141. wondered how we calculated the colors for a pixel or a line.
  3142.         
  3143. To explain this we must look at the bitplanes. Either we or the individual
  3144. bits of bit planes determine a pixels colour.
  3145.         
  3146. For example, when the pixel bit of bitplanes one and three are set but 
  3147. bitplane two is unset, we use the following formula: (1*2^0 + 0*2^1 + 
  3148. 1*2^2  = 5. This tells us that the colour comes from colour register five.
  3149. You could also use normal binary arithmetic.
  3150.         
  3151. To set a specific colour for a pixel, the opposite action is performed.
  3152. You specify the colour register to use and the graphic functions set the 
  3153. individual pixel bits for you.
  3154.         
  3155. Remember the Amiga has two colour pens, the APen and the BPen. But before
  3156. we continue with their functions, we will quickly discuss DrawModes.
  3157.         
  3158.                                 PAGE 339
  3159.         
  3160. --------------------------------------------------------------------------
  3161.         
  3162. 11.1 THE DRAWMODES.
  3163.         
  3164. The drawmodes determine the relationship betweenthe existing pixel bits
  3165. and the pixel bit written to their locations in the bitplanes. The 
  3166. available bit manipulation operations are OR, AND, NOT and EXOR.
  3167.         
  3168. In the normal mode (SetDrMd (&RastPort, JAM1)) the written bits are
  3169. simply ORed with the existing bitplane bits.
  3170.         
  3171. In JAM2 mode (SetDrMd (&RastPort, JAM2)) the written bits are added using 
  3172. AND. This has the same effect as JAM1 when usig pixels and lines. However,
  3173. when using text you can see the difference immediately. A drawings bit
  3174. pattern is stored in memory as set and unset pixels. The blitter (BLock 
  3175. Imae Transferrer), which is responsible for drawing output, also copies the
  3176. unset bits of a drawing to the bitplane. When JAM2 mode is on, the 
  3177. background is overwritten with the unset bits.
  3178.         
  3179. The COMPLEMENT mode performs an EXOR operation between the existing bits
  3180. and the bits being written. The EXOR logic table looks like this:
  3181.         
  3182.         
  3183. Bitplane     Operation:^        Pixel        Result
  3184. ---------------------------------------------------
  3185. 0                               0       =    0
  3186. 0                               1       =    1
  3187. 1                               0       =    1
  3188. 1                               1       =    0
  3189.         
  3190.                                 PAGE 340
  3191.         
  3192. ---------------------------------------------------------------------------
  3193.         
  3194. With the last mode, INVERSVID, the written bits are reversed using the NOT
  3195. operator. A set bit becomes unset and an unset bit is set.
  3196.         
  3197. When using the NOT and EXOR operations you should remember that they take
  3198. place internally. You only see the results when you use INVERSVID or 
  3199. COMPLEMENT together with JAM1 or JAM2 (for example: SetDrMd (&RastPort, 
  3200. INVERSVID | JAM2). The bit pattern is written normally, as with JAM1 and 
  3201. JAM2, using OR or AND. The result is usually a chaotic coloured line or 
  3202. text with coloured spots.
  3203.         
  3204.         
  3205.                 ----------------------------------------
  3206.         
  3207. 11.2 THE FOREGROUND PEN.
  3208.         
  3209. Now that we have explained the drawing modes, we can continue with the 
  3210. drawing pens. To set the pixel colour in JAM1 mode, use SetAPen (&RastPort,
  3211. Number_of_Color_Register). When working with pixels and lines, JAM1 and 
  3212. JAM2 mode have the same effect.
  3213.         
  3214.                 ----------------------------------------
  3215.         
  3216. 11.3 THE BACKGROUND PEN.
  3217.         
  3218. When outputting text you can use JAM2 mode and the BPen (background pen)
  3219. to display highlighted text. To do this, simply select a color for the 
  3220. unset pixels on the screen using:
  3221.         
  3222. SetBPen(&RastPort, Number_of_Color_Register).
  3223.         
  3224. You should be aware that the function of the APen and BPen affect the bit 
  3225. patterns in the bitplanes. They determine the bit by bit pattern that is
  3226. always used when you write data to a specific location.
  3227.         
  3228.                                 PAGE 341
  3229.         
  3230. ---------------------------------------------------------------------------
  3231.         
  3232. 12. INTUITION AND GRAPHICS.
  3233. ---------------------------
  3234.         
  3235. Now that you have seen how to draw pixels and lines, change drawings modes 
  3236. and select drawing pens, we will show you a rather easy method to set up 
  3237. View, ViewPort etc..
  3238.         
  3239. This method involves the user interface Intuition, which enables you to 
  3240. easily access the RastPorts.
  3241.         
  3242. The first and most important step is opening the Intuition.library. You 
  3243. do this in the same way as you opened the graphic.library. But instead
  3244. of using the string name "graphics.library",you use "intuition.library".
  3245. The function looks like this:
  3246.         
  3247.         (IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.
  3248.                 library",0)).
  3249.         
  3250.                                 PAGE 343
  3251.         
  3252. ----------------------------------------------------------------------------
  3253.         
  3254. 12.1 THE INDIVIDUAL SCREEN.
  3255.         
  3256. Intuition creates screens that are completely initialised ViewPorts with a
  3257. ColorMap, a BitMap, a RastPort etc..
  3258.         
  3259. Inuition also creates a View for us. However, the most important feature
  3260. of Intuition is that it takes control of almost everything so we dont
  3261. have to do the work ourselves.
  3262.         
  3263. Basically, opening screens is reduced to two actions:
  3264.         
  3265.         1.) Initialising a NewScreen.
  3266.         
  3267.         2.) the OpenScreen call.
  3268.         
  3269. For details on the NewScreen structure please check the Appendices. We will
  3270. only briefly explain the Screen = (struct Screen *)OpenScreen(&NewScreen).
  3271. This call creates a displayed, fully functional screen with a screen 
  3272. structure that we can access. (NOTE: Screen and NewScreen are not the 
  3273. same!). &Screen->RastPort is used with most of the graphic commands to 
  3274. access the RastPort.
  3275.         
  3276. The best example of an Intuition screen is the Workbench screen where all
  3277. of the Workbench activities are performed.
  3278.         
  3279. Remember that OpenScreen uses up a lot of memory. If the pointer Screen,
  3280. For the initialised screen structure is equal to zero, then there 
  3281. isnt any available memory. When this happens, it is best to have the 
  3282. program display a short error message and exit to the CLI or Workbench.
  3283.         
  3284.                                 PAGE 344
  3285.         
  3286. ---------------------------------------------------------------------------
  3287.  
  3288. 12.2 THE WINDOW.
  3289.         
  3290. Most of the time, windows are used for graphic output. One advantage of 
  3291. windows is that a drawn line cannot pass over the window border because it
  3292. will be cut off before this can happen. This is not true for screens and 
  3293. you own ViewPorts. Under certain conditions, the excess portion of the line
  3294. will be written to memory, which causes loss of data.
  3295.         
  3296. Opening windows requires two actions:
  3297.         
  3298.         1.) Initialising a NewWindow structure and
  3299.         
  3300.         2.) Calling Window = (struct Window *) OpenWindow(&NewWindow)
  3301.         
  3302. You can access the RastPort of a window by using &Window->RastPort.
  3303.         
  3304.                 ----------------------------------------
  3305.         
  3306. 12.3 EXITING INTUITION.
  3307.         
  3308. We must return the memory used by Intuition for the same reason we had to 
  3309. return bitplane memory. You must also release the memory that was used 
  3310. by the screens and windows.
  3311.         
  3312. Close a screen using CloseScreen (Screen). The window is closed in the 
  3313. same way with CloseWindow(Window). It is very important that you close 
  3314. the windows before closing the screens otherwise you will receive 
  3315. Guru Meditations.
  3316.         
  3317. Obviously, you must also close the graphic.library and Intuition.Library:
  3318.         
  3319.         Close.Library(IntuitionBase)
  3320.         
  3321.                                 PAGE 345
  3322.         
  3323. ---------------------------------------------------------------------------
  3324.         
  3325. 13. FILLING AREAS IN C.
  3326.         
  3327. Now that we know how Intuition can help us, we can being working on
  3328. "areas".
  3329.         
  3330.         
  3331. 13.1 A Flood Function.
  3332.         
  3333. We can fill connected areas using the "Flood" function. For a pictorial
  3334. image of how flood works, compare Flood to pouring paint into a bathtub.
  3335. If you do notpour more that the tub can hold, the paint will not flow past
  3336. the edge. However, the effect would be completey different if the tub had
  3337. a crack in it causing the paint to spill out of the tub.
  3338.         
  3339. We determine the edges for a Flood function by drawing a frame around the
  3340. area we want filled. This frame does not have to be square or have a 
  3341. specific shape. To perform the fill you must specify coordinates that
  3342. are inside the area to be filled:
  3343.         
  3344.         Flood(&RastPort,Mode,x,y)
  3345.         
  3346. With this type of fill, you must use a mode parameter equal to zero. This
  3347. means that you fill all pixels, using the curent drawing colour in the
  3348. current drawing mode, with the current fill pattern until you reach a 
  3349. border.
  3350.         
  3351. As explained above, you set the border by drawing a completely closed 
  3352. frame in a specific colour. To set the border colour use SetOPen(&RastPort,
  3353. Color_of_Frame). (OPen = AOLPen = Area Outline Pen = Color of the surface).
  3354.         
  3355. When the mode parameter us equal to one a slightly different fill method
  3356. is being used. The colour of the frame is no longer important. You only
  3357. fill the connected area that have the same colour as the pixel at the
  3358. selected X/Y coordinate.
  3359.         
  3360. You should be careful when using the flood function because it uses up a 
  3361. large amount of memory.
  3362.         
  3363. Due to a recursive algorithm you have to prepare a temporary raster (a 
  3364. temporarily used bitplane). This bitplane must be at least as large as 
  3365. the object you want to fill. 
  3366.         
  3367.                                 PAGE 347
  3368.         
  3369. ---------------------------------------------------------------------------
  3370.         
  3371. It is much safer to create a complete additional bitplane (AllocRaster).
  3372.         
  3373. Then you can make this memory available to the TmpRas structure and pass
  3374. this information to the RastPort.
  3375.         
  3376.         InitTmpRas (&TmpRas, &Memoryaddress, MemorySize)
  3377.         RastPort.TmpRas = &TmpRas
  3378.         
  3379. or
  3380.         
  3381.         RastPort.TmpRas = InitTmpRas(&TmpRas,&Memoryaddress,MemorySize)
  3382.         
  3383. Remember that you have to return the memory for the additional bitplane
  3384. when you are finished.
  3385.         
  3386.                                 PAGE 348
  3387.         
  3388. ---------------------------------------------------------------------------
  3389.  
  3390. 13.2 FILLING RECTANGLES ?
  3391.         
  3392. Besides filling connected areas, the Amiga can also fill simpler areas. 
  3393. This is an important reason for the blitter.
  3394.         
  3395. You can fill rectangles with the RectFill(&RastPort,x1,y1,x2,y2) command.
  3396. The 1,y1 coordinates set the upper left corner and the x2,y2 coordinates
  3397. set the lower right corner for the filled rectangle. Please make sure that
  3398. the upper left coordinates are really to the left and above the coordinates
  3399. for the lower right corner. You will get a Guru and a system lockup if 
  3400. your coordinatesare not correctly specified.
  3401.         
  3402. This command automatically draws the frame for the filled rectangle. you 
  3403. set the color for the frame with OPen(&RastPort,Color_of_Frame).
  3404.         
  3405. If you want to fill the rectangle without a frame, you use the macro 
  3406. BNDRYOFF (&RastPort) whih stands for BOUNDARY OFF. This macro simply clears
  3407. the AREAOUTLINE bit in the flag variable of the RastPort. To fill with the
  3408. visibile frame again, restore the areaoutline bit, use RastPort.Flags 
  3409. |= AREAOUTLINE. Changing the colour of the OPen (with SetOPPen()) auto-
  3410. matically sets this bit.
  3411.         
  3412. The following program uses this method of area filling without requiring
  3413. a TmpRas (additional bitplane):
  3414.         
  3415.         
  3416.         /*****************************************************/
  3417.         /*                     Hanoi.c                       */
  3418.         /* This program shows you firsthand the Tower of     */
  3419.         /* Hanoi and the use of the RectFill() command.      */
  3420.         /*                                                   */
  3421.         /* Compiled with : Lattice V5.                       */
  3422.         /*****************************************************/
  3423.         
  3424.         
  3425.         #include "exec/types.h"
  3426.         #include "exec/devices.h"
  3427.         #include "intuition/intuition.h"
  3428.         #include "intuition/intuitionbase.h"
  3429.         #include "graphics/gfx.h"
  3430.         #include "graphics/gfxbase.h"
  3431.         #include "graphics/gfxmacros.h"
  3432.         #include "graphics/copper.h"
  3433.         #include "graphics/gels.h"
  3434.         
  3435.                                 PAGE 349
  3436.         
  3437. ---------------------------------------------------------------------------
  3438.         
  3439.         #include "graphics/regions.h"
  3440.         #include "devices/keymap.h"
  3441.         #include "hardware/blit.h"
  3442.         
  3443.         #define GFX (struct GfxBase *)
  3444.         #define INT (struct IntuitionBase *)
  3445.         #define SCR (struct Screen *)
  3446.         
  3447.         #define MAXHEIGHT 30     /* maximum 30 disks.*/
  3448.         
  3449.         #define WIDTH 640
  3450.         #define HEIGHT 200
  3451.         #define RPort &Screen->RastPort      /* Our rastport */
  3452.         
  3453.         struct NewScreen Newscreen = 
  3454.             {
  3455.                 0,0,WIDTH,HEIGHT,2,
  3456.                 1,0,HIRES,CUSTOMSCREEN,
  3457.                 NULL,NULL,NULL
  3458.             };
  3459.         
  3460.         char *String = "Tower of Hanoi with RectFill()";
  3461.         
  3462.         struct Screen *Screen;
  3463.         struct GfxBase *GfxBase;
  3464.         struct IntuitionBase *IntuitionBase;
  3465.         
  3466.         UWORD pattern[4] = {0x9248,0x2492,0x4924,0x9248};
  3467.         long pos[3];                                /* For pin position */
  3468.         
  3469.         long pole[3][MAXHEIGHT],                /* for which pin at     */
  3470.                                                 /* which Position,      */
  3471.                                                 /* which disk ?         */
  3472.         
  3473.             height[3] = {0,0,0};                /* how many disks on    */
  3474.                                                 /* the pins ??          */
  3475.         
  3476.         long width;
  3477.         long disks; /* How many disks on the starting tower */
  3478.         long high, offset;
  3479.         
  3480.         char *LeftMouse = (char *)0xbfe001;
  3481.         
  3482.         VOID turm();                /* Forward Declaration */
  3483.         VOID init();
  3484.         VOID build_up();
  3485.         VOID draw();
  3486.         
  3487.         /*******************************************/
  3488.         /* Here we go !                            */
  3489.         /*******************************************/
  3490.         
  3491.         main(argc,argv)                /* Get argument */
  3492.         
  3493.                                 PAGE 350
  3494.         
  3495. ---------------------------------------------------------------------------
  3496.  
  3497.         int argc;
  3498.         char *argv[];
  3499.         {
  3500.             long i,j, length;
  3501.         
  3502.             if (!(Argc==2))
  3503.                 {
  3504.                     printf(" Tower Height : ");
  3505.                     scanf ("%ld", &disks);
  3506.                 }
  3507.             else
  3508.                     sscanf(argv[1],"%ld",&disks);
  3509.         
  3510.             if (disks >= MAXHEIGHT)
  3511.                 {
  3512.                     printf(" Too many disks !!!\n");
  3513.                     exit(1);
  3514.                 }
  3515.         
  3516.         
  3517.                     /* Calculate Pin (x-) position for display */
  3518.             
  3519.             pos[0] = WIDTH/6+5;                /* Left */
  3520.             pos[1] = WIDTH/2;                  /* middle */
  3521.             pos[2] = (WIDTH/6)*5-5;            /* Right */
  3522.         
  3523.             width = (WIDTH/6)/disks-2;   /* Width difference */
  3524.         
  3525.             init();
  3526.         
  3527.             SetRGB4(&Screen->ViewPort,0,0,0,0);  /* Set colours */
  3528.             SetRGB4(&Screen->ViewPort,1,15,15,0);
  3529.             SetRGB4(&Screen->ViewPort,2,0,15,15);
  3530.             SetRGB4(&Screen->ViewPort,3,15,0,15);
  3531.                                             
  3532.                                             /* Initialise Pins */
  3533.         
  3534.             for (i=0; i<MAXHEIGHT; i++)
  3535.                 for(j=0; j<3 ; j++)
  3536.                     pole[j][i] = 0;
  3537.                                         /* Erase Pin */
  3538.         
  3539.             for (i=0; i<disks; i++)
  3540.                     pole[0][i] = disks - 1;
  3541.                                     /* Smallest disk to top */
  3542.             
  3543.             height[0] = disks;        /* 1 pin has n disks */
  3544.             SetAfPt(RPort,pattern,2); /* Set fill pattern  */
  3545.             SetOPen(RPort,2);         /* Framing pen       */
  3546.         
  3547.             high = (HEIGHT*3/8)/disks;        
  3548.                                       /* How high is one disk ? */
  3549.             
  3550.             offset = HEIGHT*3/8;
  3551.             
  3552.             build_up();              /* Build first display */
  3553.         
  3554.                                 PAGE 351
  3555.         
  3556. ---------------------------------------------------------------------------
  3557.  
  3558.         SetAPen(RPort,3);        /* String output */
  3559.         
  3560.         Length = TextLength(RPort, String, strlen(String))/2;
  3561.         Move(RPort,WIDTH/2-Length,Screen->RastPort,TxBaseline);
  3562.         Text(RPort,String,strlen(String));
  3563.         
  3564.                                                 /* Start recursions */
  3565.         turm (disks,1,2,3);
  3566.             
  3567.         while ((*LeftMouse & 0x40) == 0x40);
  3568.                                                 /* Wait a little bit */
  3569.         CloseScreen(Screen);
  3570.         CloseLibrary(GfxBase);
  3571.         CloseLibrary(IntuitionBase);
  3572.         return(0);
  3573.     }
  3574.         
  3575.         /******************************************************/
  3576.         /* This recursive procedure moves the disks from pin  */
  3577.         /* one to pin three.                                  */
  3578.         /*----------------------------------------------------*/
  3579.         /* Entry Parameters:                                  */
  3580.         /*       n :: = Number of disks.                      */
  3581.         /*       l :: = Number of left pin.                   */
  3582.         /*       m :: =   ""   "" middle pin.                 */
  3583.         /*       r :: =   ""   "" right  pin.                 */
  3584.         /*----------------------------------------------------*/
  3585.         /* Returned values : none.                            */
  3586.         /******************************************************/
  3587.         
  3588.         VOID turm(n,l,m,r)
  3589.         long n,l,m,r;
  3590.         {
  3591.             if (n==1)
  3592.                 {
  3593.                     pole[r-1][height[r-1]] = 
  3594.                         pole[l-1][height[1-1]-1];
  3595.             
  3596.                     height[r-1]++;
  3597.                     draw(r-1, l-1);
  3598.                     pole[l-1][height[l-1]-1] = 0;
  3599.                     height[l-1]--;
  3600.                 }
  3601.             else
  3602.                 {
  3603.                     turm(n-1,l,r,m);
  3604.                         pole[r-1][height[r-1]] =
  3605.                             pole[-1][height[l-1]-1];
  3606.                         
  3607.                         height[r-1]++;
  3608.                         draw(r-1,l-1);
  3609.                         pole[l-1][height[l-1]-1] = 0;
  3610.                         height[l-1]--;
  3611.         
  3612.                                 PAGE 352
  3613.         
  3614. ---------------------------------------------------------------------------
  3615.         
  3616.                 turm(n-1,m,l,r);
  3617.                 }
  3618.             }
  3619.         
  3620.         /*****************************************************/
  3621.         /* This procedure opens the required libraries and   */
  3622.         /* a screen.                                         */
  3623.         /*---------------------------------------------------*/
  3624.         /* Entry parameters : None,                          */
  3625.         /*---------------------------------------------------*/
  3626.         /* Returned values : None.                           */
  3627.         /*****************************************************/
  3628.         
  3629.         VOID init()
  3630.         {
  3631.             GfxBase = GFX OpenLibrary("graphics.library",0);
  3632.             IntuitionBase = INT OpenLibrary("intuition.library",0);
  3633.             Screen = SCR OpenScreen(&NewScreen);
  3634.         }
  3635.         
  3636.         /**************************************************/
  3637.         /* This procedure builds the three towers to start*/
  3638.         /*------------------------------------------------*/
  3639.         /* Entry parameters : none                        */
  3640.         /*------------------------------------------------*/
  3641.         /* Returned values  : none                        */
  3642.         /**************************************************/
  3643.         
  3644.         VOID Build_up()
  3645.         {
  3646.             long i,j;
  3647.         
  3648.             WaitTOF();        /* Synchronised output with beam */
  3649.             SetRast(RPort,0);
  3650.             SetAPen(RPort,1);
  3651.         
  3652.             for (j=0; j<3; j++)
  3653.                 for(i=1; i<disks; i++)
  3654.                     RectFill(RPort, pos[j]-(pole[j][disks-i]*width),
  3655.                              ((i-1)*high)+offset, pos[j]+(pole[j][disks-i]
  3656.                              *width), (i*high)+offset);
  3657.         }
  3658.         
  3659.         
  3660.         /*********************************************************/
  3661.         /* This procedure erases and sets the top disk for       */
  3662.         /* two pins.                                             */
  3663.         /*-------------------------------------------------------*/
  3664.         /* Entry Parameters:                                     */
  3665.         /*  new := Pin, where new disk is placed.                */
  3666.         /*  old := Pin, where disk is removed from.              */
  3667.         /*-------------------------------------------------------*/
  3668.         /* Returned values: none.                                */
  3669.         /*********************************************************/
  3670.         
  3671.                                 PAGE 353
  3672.         
  3673. ---------------------------------------------------------------------------
  3674.         
  3675.         VOID draw(new,old)
  3676.         long new, old;
  3677.         {
  3678.             SetAPen(RPort,0);
  3679.             SetOPen(RPort,0);
  3680.             
  3681.             if(height[old]-1 == 0)        /* Last pin ? */
  3682.         
  3683.             RectFill(RPort, pos[old][height[old]-1]*width,(disks-height
  3684.                      [old])*high+offset, pos[old]+pole[old][height[old]-1]
  3685.                      *width, (disks-height[old]+1)*high+offset);
  3686.         
  3687.             else
  3688.             
  3689.             RectFill(RPort, pos[old-pole[old][height[old]-1]*width,
  3690.                      (disks-height[old])*high+offset, pos[old]+pole[old]
  3691.                      [height[old]-1]*width, (disks-height[old]+1)*high
  3692.                      +offset-1);
  3693.         
  3694.             SetAPen(RPort,1);        /* Write new disk */
  3695.             SetOPen(RPort,2);
  3696.         
  3697.             RectFill(RPort,pos[old],(disks-height[old])*high+offset, 
  3698.                      pos[old], (disks-height[old]+1)*high+offset);
  3699.         
  3700.             RectFill(RPort, pos[new]-pole[new][height[new]-1]*width,
  3701.                      (disks-height[new])*high+offset, pos[new]+pole[new]
  3702.                      [height[new]-1]*width, (disks-height[new]+1)*high+
  3703.                      offset);
  3704.         
  3705.             Delay(Screen->MouseX/10);
  3706.                         /* Pause depending upon the mouse position. */
  3707.       }
  3708.         
  3709. If you look very closely, you can see that the rectangles drawn by the 
  3710. program are not completely filled. There are many small holes that allow 
  3711. the background to show through.
  3712.         
  3713. We were able to do this becuase we created our own fill pattern as we 
  3714. mentioned in the Flood function section.
  3715.         
  3716. In addition, there are two types of fill patterns, single coloured and 
  3717. multicoloured. Both of these fill patterns requie a height that is set in 
  3718. powers of two (1,2,4,8 ... rows) and a width of 16 pixels (bits). WE
  3719. store the fill pattern in memory, for example in a word array.
  3720.         
  3721.                                 PAGE 354
  3722.         
  3723. ---------------------------------------------------------------------------
  3724.         
  3725. Single coloured patterns require only a single bitplane. The colours of the
  3726. APen (BPen) and drawing mode also have an effect on the area's appearance.
  3727.         
  3728. With multi-colored planes you must specify a bit pattern for every plane.
  3729.         
  3730. By using the current drawing mode, you can write these patterns directly 
  3731. into the bitplanes. The only way we can affect them there is by changing
  3732. the drawing mode.
  3733.         
  3734. To use these patterns with the graphics functions, we must get help from 
  3735. the SetAfPt(&RastPort, &BitPattern, Height) function (Set Area Fill 
  3736. Pattern).
  3737.         
  3738. We specify the height as an exponent of the power of two. So a pattern that
  3739. is eight rows high then has a height of 3 (3^2 = 8).
  3740.         
  3741. However, this only applies to single coloured patterns. When using multi
  3742. coloured patterns, we set the exponent to a negative value, -3 instead
  3743. of 3.
  3744.         
  3745.                                 PAGE 355
  3746.         
  3747. ---------------------------------------------------------------------------
  3748.         
  3749. 13.3 POLYGON FILLING: AREA FILL MAKES IT POSSIBLE.
  3750.         
  3751. The AREA... functions provide another method for filling in areas. These 
  3752. commands enable you to draw filled polygons with a frame drawn in the
  3753. OPen colour.
  3754.         
  3755. Before you are able to use these commands, some preparatory work is 
  3756. required.
  3757.         
  3758. The most important setup is, as in the FLOOD function, the TmpRas structure.
  3759. You must initialise this in the RastPort where you want to draw your 
  3760. polygons.
  3761.         
  3762. You must also initialise the AreaInfo structure that will contain the 
  3763. individual base points of the polygon. To do this, use the function:
  3764.         
  3765.         InitArea(&AreaInfo, &CoordsBuffer, NumCoords)
  3766.         
  3767. InitArea ensures that the AreaInfo structure for the buffer and the address
  3768. of this buffer are established. These will later contain the polygon 
  3769. coordinates. You also have to set the maximum number of coordinates for 
  3770. this buffer (NumCoords). Your buffer must contain (NumCoords+1)*5 bytes.
  3771. The easiest way to do this is to assign the memory by using a char array
  3772. (char buffer[ (NumCoords+1)*5]).
  3773.         
  3774. After you pass the initialised AreaInfo structure to the RastPort 
  3775. (RastPort.AreaInfo = &AreaInfo) you can set up your polygon. You always 
  3776. set the first coordinate with AreaMove(&RastPort, x, y). AreaMove signals
  3777. that you are creating a new polygon.
  3778.         
  3779. Now you can set the rest of the polygon base points using 
  3780. AreaDraw(&RastPort, x, y). In this case x and y also specify the coordinates
  3781. of the pixel within the RastPort.
  3782.         
  3783. You set the last pixel of a polygon with AreaEnd (&RastPort, x, y). This 
  3784. also takes care of drawing the polygon (a submode of the Flood function)
  3785. and filling it.
  3786.         
  3787. You can also use the BNDRYOFF (&RastPort) macro to turn off the boundary
  3788. lines for the polygon.
  3789.         
  3790.                                 PAGE 356
  3791.         
  3792. ---------------------------------------------------------------------------
  3793.         
  3794. To complete this chapter, we have included a special program. This program
  3795. allows you to outline, with the mouse, objects that we can then rotate
  3796. three dimensionally.
  3797.      
  3798.      
  3799.      /********************************************************/
  3800.      /*                        Rotateit.c                    */
  3801.      /*                                                      */
  3802.      /* This program creates three dimensional rotation      */
  3803.      /* objects that we build with Area()... and display.    */
  3804.      /* Compiled with Lattice v3.1                           */
  3805.      /*   Will require major changes for Lattice V5          */
  3806.      /*   and Aztec 3.6a                                         */
  3807.      /********************************************************/
  3808.      
  3809.      #include "exec/types.h"
  3810.      #include "exec/memory.h"
  3811.      #include "exec/devices.h"
  3812.      #include "devices/printer.h"
  3813.      #include "devices/keymap.h"
  3814.      #include "graphics/gfx.h"
  3815.      #include "graphics/gfxmacros.h"
  3816.      #include "graphics/gfxbase.h"
  3817.      #include "graphics/rastport.h"
  3818.      #include "graphics/text.h"
  3819.      #include "graphics/regions.h"
  3820.      #include "graphics/gels.h"
  3821.      #include "graphics/copper.h"
  3822.      #include "hardware/blit.h"
  3823.      #include "intuition/intuition.h"
  3824.      
  3825.      #define WIDTH 640
  3826.      #define HEIGHT 400                        /* Size of Screen */
  3827.      
  3828.                              PAGE 357
  3829.      
  3830. --------------------------------------------------------------------------
  3831.      
  3832.      #define INCREMENT 3        /* Angle Increment */
  3833.      #define MAXITEMS 5        /* 5 menu items */
  3834.      
  3835.      #define MAXCOORDS 30     /* Max 30 pixels for outline */
  3836.      #define MAXROTS 60        /* 60 roatations */
  3837.      
  3838.      #define RastPort Window->RPort        /* Simple access to the */
  3839.                                            /* window's RastPort    */
  3840.      
  3841.      #define MAXAREA (MAXCOORDS-1)*MAXROTS
  3842.                                            /* How many areas       */
  3843.      
  3844.      char ASCString[6];                /* for itoa() */
  3845.      
  3846.      struct GfxBase *GfxBase = 0;
  3847.      struct IntuitionBase *IntuitionBase = 0;
  3848.      struct Screen *Screen = 0;
  3849.      struct Window *Window = 0;         /* Basepointers */
  3850.      
  3851.      struct MenuItem Items[MAXITEMS];   /* Menu entries */
  3852.      struct IntuiText Texts[MAXITEMS];  /* Menu Text    */
  3853.      
  3854.      struct Menu Menus;                 /* Menu         */
  3855.      
  3856.      struct NewWindow NewWindow;
  3857.      struct NewScreen NewScreen;
  3858.      
  3859.      char *IString[MAXITEMS] = {
  3860.                                  0x000,0x0111,0x0222,0x0333,
  3861.                                  0x0444,0x0555,0x0666,0x0777,
  3862.                                  0x0888,0x0999,0x0aaa,0x0bbb,
  3863.                                  0x0ccc,0x0ddd,0x0eee,0x0fff
  3864.                                };
  3865.                              /* Own color table with grey shades */
  3866.      
  3867.      long Status = TRUE;
  3868.      struct TmpRas TmpRas;   /* TmpRas for Area()..... */
  3869.      struct AreaInfo AreaInfo; /* AreaInfo for Area().... */
  3870.      
  3871.      long *Pointer = 0;        /* Help pointer */
  3872.      
  3873.      UBYTE AreaBuffer[(4+1)*5]; /* Pixel storage for Area.    */
  3874.                                 /* Always 4 (+1) pixels per area */
  3875.      
  3876.                              PAGE 358
  3877.      
  3878. ---------------------------------------------------------------------------
  3879.      
  3880.      int sintab[91] = {
  3881.                        0,   285,  571,  857,1142,1427,1712,1996,2280,
  3882.                        2563,2845,3126,3406,3685,3963,4240,4516,4790,
  3883.                        5062,5334,5603,5871,6137,6401,6663,6924,7182,
  3884.                        7438,7691,7943,8192,8438,8682,8923,9161,9397,
  3885.                    9630,9860,10086,10310,10531,10748,10963,11173,11381,
  3886.                    11584,11785,11982,12175,12365,12550,12732,12910,13084,
  3887.                    13254,13420,13582,13740,13894,14043,14188,14329,14466,
  3888.                    14598,14725,14848,14967,15081,15190,15295,15395,15491,
  3889.                    15582,15662,15749,15825,15897,15964,16025,16082,16135,
  3890.                    16182,16224,16261,16294,16321,16244,16361,16374,16381,
  3891.                    16384
  3892.                       };
  3893.      
  3894.                    /* Sine table is calculated :                       */
  3895.                    /* sintab[x]=sin[x] * 16384 (x=1,2,...,90)         */
  3896.                    /* See sincos(), sin(), cos()                      */
  3897.      
  3898.      
  3899.      int Pixel[MAXROTS][MAXCOORDS][3];
  3900.      int Mother[MAXROTS][MAXCOORDS][3];
  3901.              /* Mother array is calculated for the Rotation      */
  3902.              /* object from the input outlines and is then       */
  3903.              /* Arrays. This is necessary because through the    */
  3904.              /* many transformations a single Array would suffer */
  3905.              /* irreparable damage that would have a negative    */
  3906.              /* effect on the visible object                     */
  3907.      
  3908.      int Area[MAXREAD][4][3];
  3909.              /* Here we store the Areas calculated from the      */
  3910.              /* Pixels.                                          */
  3911.      int CoordArray[MAXCOORDS][2];
  3912.              /* Here we store the coordinates for the entire     */
  3913.              /* outlines.                                        */
  3914.      
  3915.      int x[MAXROTS][MAXCOORDS];
  3916.      int y[MAXROTS][MAXCOORDS];
  3917.              /* For transformation 3D -> 2D (Screen)                 */
  3918.      
  3919.      int Index[MAXAREA+1];        /* For sorting */
  3920.      
  3921.      long ProzZ = 1500,           /* Projections Central *
  3922.           ProzY = 0,
  3923.           ProzX = 0;
  3924.      
  3925.      long d = 0;                 /* Separate projection plane */
  3926.                                  /* Projection Central        */
  3927.      
  3928.      long bbpx = 0,
  3929.           bbpy = 0,              /* Observation Points */
  3930.           bbpz = 0;
  3931.      
  3932.      long AngleX = 0,
  3933.           AngleY = 0,            /* Display Angle      */
  3934.           AngleZ = 0;
  3935.      
  3936.                              PAGE 359
  3937.      
  3938. ---------------------------------------------------------------------------
  3939.      
  3940.      VOID Show();
  3941.      long Average();
  3942.      char *Itoa();
  3943.      VOID Shade();
  3944.      VOID Init();
  3945.      VOID Rot();
  3946.      long sincos();
  3947.      long sin();
  3948.      long cos();
  3949.      long EnterCoords();
  3950.      VOID make_menu();
  3951.      struct IORequest *CreateExtIo();
  3952.      VOID DeleteExtIo();
  3953.      VOID HardCopy();
  3954.      
  3955.      /********************************************************/
  3956.      /* This function initialises the specified NewScreen    */
  3957.      /* and NewWindow structures for OpenScreen(), and       */
  3958.      /* OpenWindow().                                        */
  3959.      /*------------------------------------------------------*/
  3960.      /* Entry Parameters: to initialise NewScreen -          */
  3961.      /*                                 structure (NS)       */
  3962.      /*                   to initialise NewWindow -          */
  3963.      /*                                 structure (NW)       */
  3964.      /*------------------------------------------------------*/
  3965.      /* Returned Values : None                               */
  3966.      /********************************************************/
  3967.      
  3968.      VOID InitScreenWindow (NS,NW)
  3969.      struct NewScreen *NS;
  3970.      struct NewWindow *NW;
  3971.      {
  3972.          NS->LeftEdge = 0;        NS->TopEdge = 0;
  3973.          NS->Width = WIDTH;       NS->Height= HEIGHT;
  3974.          NS->Depth = 4;          
  3975.          NS->DetailPen = 1;       NS->BlockPen = 0;
  3976.          NS->ViewModes = 0;
  3977.      
  3978.          if (WIDTH > 320) NS->ViewModes |= HIRES;
  3979.          if (HEIGHT > 200) NS->ViewModes := LACE;
  3980.      
  3981.          NS->Type = CUSTOMSCREEN;
  3982.          NS->Font = NULL;
  3983.          NS->DefaultTitle = "";
  3984.          NS->Gadgets = NULL;       NS->CustomBitMap = NULL;
  3985.      
  3986.          NW->LeftEdge = 0;         NW->TopEdge = 0;
  3987.          NW->Width = WIDTH;        NW->Height = HEIGHT;
  3988.          NW->DetailPen = 6;        NW->BlockPen = 0;
  3989.          NW->IDCMPFlags = NULL;
  3990.          NW->Flags = BORDERLESS | ACTIVATE | NOCAREREFRESH 
  3991.                                 | REPORTMOUSE;
  3992.          NW->FirstGadget = NULL;
  3993.          NW->CheckMark = NULL;    NW->Title = "";
  3994.          NW->Screen = NULL;       NW->BitMap = NULL;
  3995.          NW->MinWidth = NW->MinHeight = NW->MaxWidth =
  3996.          NW->MaxHeight = 0;
  3997.          NW->Type =CUSTOMSCREEN;
  3998.      }
  3999.      
  4000.                              PAGE 360
  4001.      
  4002. ---------------------------------------------------------------------------
  4003.      
  4004.      /*********************************************************/
  4005.      /* This function builds the mnu and the individual       */
  4006.      /* Items.                                                */
  4007.      /*-------------------------------------------------------*/
  4008.      /* Entry Parameters : None                               */
  4009.      /*-------------------------------------------------------*/
  4010.      /* Returned Values  : None                               */
  4011.      /*********************************************************/
  4012.      
  4013.      VOID BuildUpMenu()
  4014.      {
  4015.          long i;
  4016.          
  4017.          for (i=0; i<MAXITEMS; i++)
  4018.              {
  4019.                  Items[i].LeftEdge = 1;
  4020.                  Items[i].TopEdge = i*10;
  4021.                  Items[i].Width = 112;   Items[i].Height = 10;
  4022.                  Items[i].Flags = ITEMTEXT | ITEMENABLED | HIGHCOMP;
  4023.                  Items[i].MutualExclude = NULL;
  4024.                  Items[i].ItemFill = (APTR) &Texts[i];
  4025.                  Items[i].SelectFill = NULL;
  4026.                  Items[i].Command = NULL;
  4027.                  Items[i].SubItem = NULL;
  4028.                  Items[i].NextSelect = NULL;
  4029.          
  4030.                  Texts[i].FrontPen = 6;    Texts[i].BackPen = 0;
  4031.                  Texts[i].DrawMode = JAM1; Texts[i].LeftEdge = 1;
  4032.                  Texts[i].TopEdge = 1;
  4033.                  Texts[i].ITextFont = NULL;
  4034.                  Texts[i].IText = IString[i];
  4035.                  Texts[i].NextText = NULL;
  4036.              }
  4037.          
  4038.                              PAGE 361
  4039.      
  4040. ---------------------------------------------------------------------------
  4041.      
  4042.          for (i=0; i<MAXITEMS-1; i++)
  4043.              Items[i].NextItem = &Items[i+1];
  4044.              Items[MAXITEMS-1].NextItem = NULL;
  4045.          
  4046.              Menus.NextMenu =NULL;        Menus.LeftEdge = 10;
  4047.              Menus.TopEdge = 0;           Menus.Width = 110;
  4048.              Menus.Height = 10;           Menus.Flags = MENUENABLED;
  4049.              Menus.MenuName = " Projects";
  4050.              Menus.FirstItem = &Items(0);
  4051.      }
  4052.      
  4053.      /********************************************************/
  4054.      /* This function ends the Program, but not before       */
  4055.      /* closing all the open libraries, Screens and Windows  */
  4056.      /* and giving back all the extra allocated memory.      */
  4057.      /*------------------------------------------------------*/
  4058.      /* Entry Parameters : Output string (poss. Errormessage)*/
  4059.      /*------------------------------------------------------*/
  4060.      /* Returned Values  : None                              */
  4061.      /********************************************************/
  4062.      
  4063.      VOID CloseIt(s)
  4064.      char *s;
  4065.      {
  4066.          puts(s);
  4067.          if (Pointer) FreeMem(Pointer,RASSIZE(WIDTH, HEIGHT/2));
  4068.                                              /* TmpRas memory */
  4069.          
  4070.          if (Window) {
  4071.                       ClearMenuStrip(Window);
  4072.                       CloseWindow(Window);
  4073.                      }
  4074.          if (Screen) CloseScreen(Screen);
  4075.          if (GfxBase) CloseLibrary(GfxBase);
  4076.          if (IntuitionBase) CloseLibrary(IntuitionBase);
  4077.          
  4078.          exit(0);
  4079.      }
  4080.      
  4081.      /********************************************************/
  4082.      /* This opens all the required (Library, Screen,        */
  4083.      /* Window) for the Program.                             */
  4084.      /*------------------------------------------------------*/
  4085.      /* Entry Parameters : None                              */
  4086.      /*------------------------------------------------------*/
  4087.      /* Returned Values  : None                              */
  4088.      /********************************************************/
  4089.      
  4090.      VOID OpenLibs()
  4091.      {
  4092.          InitScreenWindow(&NewScreen, &NewWindow);
  4093.          
  4094.          if ((GfxBase = (struct GfxBase *)
  4095.              OpenLibrary("graphics.library",0)) == 0)
  4096.          CloseIt("No graphics !!!");
  4097.      
  4098.          if ((IntuitionBase = (struct IntuitionBase *)
  4099.              OpenLibrary("intuition.library",0)) == 0)
  4100.          CloseIt(" No intuition !!!");
  4101.      
  4102.                              PAGE 362
  4103.      
  4104. ---------------------------------------------------------------------------
  4105.      
  4106.          if ((Screen = (struct Screen *)
  4107.                 OpenScreen(&NewScreen)) == 0)
  4108.          CloseIt(" No Screen !!!");
  4109.      
  4110.          NewWindow.Screen = Screen;
  4111.          
  4112.          if ((Window = (struct Window *)
  4113.                 OpenWindow(&NewWindow)) == 0)
  4114.          CloseIt( "No Window !!!");
  4115.          
  4116.          LoadRB4(&Screen->ViewPort, &Colors[0], 16);
  4117.                                      /* Load new color */
  4118.          RemakeDisplay();            /* and display it */
  4119.      
  4120.          SetRGB4(&Screen->ViewPort,17,4,4,4);   /* Mouse pointer */
  4121.          SetRGB4(&Screen->ViewPort,18,8,8,8);   /* color         */
  4122.          SetRGB4(&Screen->ViewPort,19,13,13,13);
  4123.          
  4124.          Init();
  4125.          BuidlUpMenu();
  4126.      }
  4127.          
  4128.      
  4129.      /****************************************************************/
  4130.      /* This function switches the Intuition message transfer off.   */
  4131.      /* This is important since normally all Intuition messages are  */
  4132.      /* stored in a list (Queue) and processed once after another.   */
  4133.      /* Because we cannot react in time to these messages due to     */
  4134.      /* calculations and drawing, it is best that you switch it off. */
  4135.      /* Otherwise messages are stored (like a keypress) and then     */
  4136.      /* later processed which would be confusing to the user.        */
  4137.      /* For example, after a rotation, the key press is acted on     */
  4138.      /* that you pressed some time ago.                              */
  4139.      /*--------------------------------------------------------------*/
  4140.      /* Entry Parameters : None.                                     */
  4141.      /*--------------------------------------------------------------*/
  4142.      /* Returned Values  : None.                                     */
  4143.      /****************************************************************/
  4144.          
  4145.      VOID IDCMPoff()
  4146.      {
  4147.          SetMenuStrip(Window,NULL);
  4148.          ModifyIDCMP(Window,NULL);
  4149.                      /* Separate Menu Row From Window. */
  4150.      }
  4151.      
  4152.       
  4153.      /****************************************************************/
  4154.      /* This allows intuition to send messages again.                */
  4155.      /*--------------------------------------------------------------*/
  4156.      /* Entry Parameters : None.                                     */
  4157.      /*--------------------------------------------------------------*/
  4158.      /* Returned Values  : None.                                     */
  4159.      /****************************************************************/
  4160.      
  4161.                              PAGE 363
  4162.      
  4163. ---------------------------------------------------------------------------
  4164.      
  4165.      VOID IDCMPon()
  4166.      {
  4167.          ModifyIDCMP(Window, RAWKEY | MOUSEBUTTONS | MENUPICK);
  4168.          SetMenuStrip(Window,&Menus);       /* Link menu with  */
  4169.                                             /* Window.         */
  4170.      }
  4171.      
  4172.      
  4173.      /****************************************************************/
  4174.      /* This routine uses the shape outline to calculate the         */
  4175.      /* coordinates for the 3 dimensional rotation figure. Rotation  */
  4176.      /* 3D (Y axis).                                                 */
  4177.      /*--------------------------------------------------------------*/
  4178.      /* Entry Parameters :                                           */
  4179.      /*                    rot = Number of Rotations.                */
  4180.      /*                    ko  = Number of coordinates for outlines  */
  4181.      /*--------------------------------------------------------------*/
  4182.      /* Returned Values  : none.                                     */
  4183.      /****************************************************************/
  4184.      
  4185.      VOID Rotate(rot,ko)
  4186.      long rot,ko;
  4187.      {
  4188.          long i,j;
  4189.          long s,c;
  4190.          
  4191.          Move(RastPort,0,RastPort->TxBaseline);
  4192.          Text(RastPort,"Calculating Rotation Matrix ...",29);
  4193.          
  4194.          for(i=0; i<rot; i++)
  4195.              {
  4196.                  s=sin((360/rot)*i);  /* Calculate rotation angle */
  4197.                  c=cos((360/rot)*i);
  4198.          
  4199.                  for (j=0; j<ko; j++)
  4200.                    {
  4201.                      Pixel[i][j][0] = Mother[i][j][0] =
  4202.                          (CoordArray[j][0]*c)/16384;        /* X */
  4203.                      Pixel[i][j][1] = Mother[i][j][1] = 
  4204.                          CoordArray[j][1];                  /* Y */
  4205.                      Pixel[i][j][2] = Mother[i][j][2] = 
  4206.                          -(CoordArray[j][0]*s)/16384;       /* Z */
  4207.          
  4208.          /* 'Mother' is inchanged and is used by the entire program */
  4209.          /* as a mother-Mask.                                       */
  4210.                    }
  4211.              }
  4212.          Move (RastPort,0,RastPort->TxBaseline);
  4213.          Text (RastPort,"                             ",29);
  4214.          
  4215.      /****************************************************************/
  4216.      /* This routine calculates and draws the 2 dimensional picture  */
  4217.      /* from the three dimensional coordinates.                      */
  4218.      /*--------------------------------------------------------------*/
  4219.      /* Entry Parameters : rot = Number of Rotations.                */
  4220.      /*                    ko  = Number of Coordinates for the       */
  4221.      /*                          outline.                            */
  4222.      /*--------------------------------------------------------------*/
  4223.      /* Returned Values  : None.                                     */
  4224.      /****************************************************************/
  4225.      
  4226.                              PAGE 364
  4227.      
  4228. ---------------------------------------------------------------------------
  4229.      
  4230.      VOID Show(rot,ko)
  4231.      long rot,ko;
  4232.      {
  4233.          long i,j,t;
  4234.          
  4235.          SetRast(RastPort,0);
  4236.          
  4237.          for(i=0; i<rot; i++)
  4238.              for(j=0; j<ko; j++)
  4239.                {
  4240.                  t = (d-pixel[i][j][2])/(ProzZ-Pixel[i][j][2]);
  4241.          
  4242.                  x[i][j] = WIDTH/2-Pixel[i][j][0]+
  4243.                             (ProzX-Pixel[i][j][0])*t;
  4244.                  y[i][j] = HEIGHT/2-Pixel[i][j][1]+(ProzY-
  4245.                             Pixel[i][j][1])*t;
  4246.                                 /* 3d - 2d transformation */
  4247.          
  4248.                  if(j>0)
  4249.                    {
  4250.                      
  4251.                      Move(RastPort,x[i][j-1],y[i][j-1]);
  4252.                      Draw(RastPort,x[i][j],y[i][j]);
  4253.                                 /* Longitudinal Support */
  4254.                    }
  4255.                  
  4256.                  if(i>0)
  4257.                    {
  4258.                      Move(RastPort,x[i-1][j],y[i-1][j]);
  4259.                      Draw(RastPort,x[i][j], y[i][j]);
  4260.                                 /* Transverse support   */
  4261.                    }
  4262.              }
  4263.      for (j=0; j<ko; j++)
  4264.          {
  4265.              Move(RastPort,x[0][j]. y[0][j]);
  4266.              Draw(RastPort,x[rot-1][j],y[rot-1][j]);
  4267.                                  /* Last transverse */
  4268.          }
  4269.      
  4270.      
  4271.      /****************************************************************/
  4272.      /* This routine calculates the middle 2 coordinates for a       */
  4273.      /* specified area.                                              */
  4274.      /*--------------------------------------------------------------*/
  4275.      /* Entry Parameters : i = Which area.                           */
  4276.      /*--------------------------------------------------------------*/
  4277.      /* Returned Value   : Middle Z coordinate for area 1            */
  4278.      /****************************************************************/
  4279.      
  4280.      long Average(i)
  4281.      long i;
  4282.      {
  4283.      
  4284.                              PAGE 365
  4285.      
  4286. ---------------------------------------------------------------------------
  4287.      
  4288.          long a,b,c,d;
  4289.          
  4290.          a=Area[i][0][2];
  4291.          b=Area[i][1][2];
  4292.          c=Area[i][2][2];
  4293.          d=Area[i][3][2];
  4294.      
  4295.          a=a+b+c+d;                /* Picture Sum and Average */
  4296.          return(a/4);
  4297.      }
  4298.          
  4299.          
  4300.      /****************************************************************/
  4301.      /* This routine converts the received Integer number to         */
  4302.      /* ASCII.                                                       */
  4303.      /*--------------------------------------------------------------*/
  4304.      /* Entry Parameters : x = Integer.                              */
  4305.      /*                    position = How many positions for         */
  4306.      /*                               entire Ascii string.           */
  4307.      /*--------------------------------------------------------------*/
  4308.      /* Returned Value   : Address of ASCII string.                  */
  4309.      /****************************************************************/
  4310.      
  4311.      char *Itoa(x,position)
  4312.      long x,position;
  4313.      {
  4314.          position--;
  4315.          if (x<0)
  4316.              {
  4317.                  ASCString[0] = '-';
  4318.                  x= -x;
  4319.              }
  4320.          else ASCString[0] = 32;
  4321.          
  4322.      do {
  4323.          ASCString[position] = (x % 10)+'0';     /* + '0' */
  4324.          position--;
  4325.          x/=10;
  4326.         } while (position > 0);
  4327.      return (ASCString);
  4328.      }
  4329.      
  4330.      
  4331.      /****************************************************************/
  4332.      /* This routine calculates and draws the Areas of the Rotation  */
  4333.      /* Object.                                                      */
  4334.      /*--------------------------------------------------------------*/
  4335.      /* Entry Parameters : rot - Number of Rotations.                */
  4336.      /*                    ko  - Number of pixels per rotation line. */
  4337.      /*                    mode- Color Shading ?                     */
  4338.      /*                    Status - Recalculate Area ?               */
  4339.      /*--------------------------------------------------------------*/
  4340.      /* Returned Values  : None.                                     */
  4341.      /****************************************************************/
  4342.          
  4343.      VOID Shade(rot, ko, Mode, Status)
  4344.      long rot, ko, Mode, Status;
  4345.      
  4346.                              PAGE 366
  4347.      
  4348. ---------------------------------------------------------------------------
  4349.      
  4350.          long i,,k;
  4351.          long count;        /* Number of areas for Rot.Object. */
  4352.          long hilf;
  4353.          long x,y;
  4354.          long t;
  4355.          long a,d,c,e;
  4356.          long w,col;
  4357.          
  4358.          count = 0;
  4359.          
  4360.          IDCMPoff();        /* No messages from intuition */
  4361.          
  4362.          if (Status == FALSE)                /* recalculate area */
  4363.          {
  4364.          Move(RastPort,0,RastPort->TxBaseline);
  4365.          Text(RastPort,"Calculating Areas... ",20);
  4366.          
  4367.          for(i=0; i<(rot-1); i++)
  4368.              for(j=0; j<(ko-1); j++)
  4369.                  {
  4370.                      for (k=0; k<3; k++)
  4371.                      {
  4372.                          Area[count][0][k] = Pixel[i][j][k];
  4373.                          Area[count][1][k] = Pixel[i][j+1][k];
  4374.                          Area[count][2][k] = Pixel[i+1][j+1][k];
  4375.                          Area[count][3][k] = Pixel[i+1][j][k];
  4376.                      }
  4377.                  count++;
  4378.              }
  4379.          
  4380.          for(j=0; j<(ko-1); j++)
  4381.              {
  4382.                  for (k=0; k<3; k++)
  4383.                      {
  4384.                          Area[count][0][k] = Pixel[rot-1][j][k];
  4385.                          Area[count][1][k] = Pixel[rot-1][j+1][k];
  4386.                          Area[count][2][k] = Pixel[0][j+1][k];
  4387.                          Area[count][3][k] = Pixel[0][j][k];
  4388.                      }
  4389.                  count++;
  4390.              }
  4391.          Move (RastPort,0,RastPort->TxBaseline);
  4392.          Text (RastPort,"Sorting Areas ... ",20);
  4393.      
  4394.          x = RastPort->cp_x;
  4395.          y = RastPort->cp_y;
  4396.          
  4397.          for(i=0; i<count; i++) Index[i+1] = 1;
  4398.                          /* Initialise Index Array */
  4399.          
  4400.          for(i=2; i<count+1; i++)
  4401.              {
  4402.                                  /* Zero area components for sorting ! */
  4403.                  hilf = Average(Index[i]);
  4404.      
  4405.                              PAGE 367
  4406.      
  4407. ----------------------------------------------------------------------------
  4408.      
  4409.                      Index[0] = Index[i];
  4410.          
  4411.                      j= i-1;
  4412.                      while(hilf < Average(Index[j]))
  4413.                        {
  4414.                          Index[j+1] = Index[j];
  4415.                          j--;
  4416.                        }
  4417.                      Index[j+1] = Index[0];
  4418.          
  4419.                      Move (RastPort,x,y);
  4420.                      Text (RastPort,itoa((count-1),5),5);
  4421.                  }
  4422.              }
  4423.      
  4424.          count = (ko-1)*rot+1;        /* Count must always  */
  4425.          SetRast(RastPort,0);         /* Be checked.        */
  4426.          
  4427.          col =0;
  4428.          if (Mode == 0)
  4429.          {
  4430.              SetAPen(RastPort,0);      /* Clear Areas and only */
  4431.              SetAPen(RastPort,9);      /* draw frame.          */
  4432.          }
  4433.          else
  4434.          {
  4435.              w=count/9;                /* Grey scale calculations */
  4436.              SetOPen(RastPort,0);      /* No frame.               */
  4437.          }
  4438.          
  4439.          for(i=1; i<count; i++)
  4440.          {
  4441.              e=Index[i];
  4442.              for(j=0; j<4; j++)        /* Draw areas.        */
  4443.                  {
  4444.                      a = Area[e][j][0];
  4445.                      b = Area[e][j][1];
  4446.                      c = Area[e][j][2];
  4447.          
  4448.                      t = (d-c)/(ProzZ-c);
  4449.                      x = WIDTH/2-a+(ProzZ-a)*t;
  4450.                      y = HEIGHT/2-b+(ProzY-b)*t;
  4451.          
  4452.                      if (Mode == 1)        /* In Grey ? */
  4453.                        {
  4454.                          if (i==w)
  4455.                            {
  4456.                              w += count/9;
  4457.                              col++;
  4458.                            }
  4459.                          SetAPen(RastPort,4+col);
  4460.                        }
  4461.                      if (j==0) AreaMove (RastPort,x,y);
  4462.      
  4463.                              PAGE 368
  4464.      
  4465. ---------------------------------------------------------------------------
  4466.      
  4467.                      else AreaDraw(RastPort,x,y);
  4468.                                  /* New polygon pixel */
  4469.                  }
  4470.              AreaEnd(RastPort);
  4471.                                  /* Polygon end + draw */
  4472.           }
  4473.          SetAPen(RastPort,9);
  4474.      }
  4475.      
  4476.      
  4477.      /****************************************************************/
  4478.      /* This routine initialises the TmpRas and AreaInfo structure   */
  4479.      /* for the RastPort.                                            */
  4480.      /*--------------------------------------------------------------*/
  4481.      /* Entry Parameters :                                           */
  4482.      /*--------------------------------------------------------------*/
  4483.      /* Returned Values  : None                                      */
  4484.      /****************************************************************/
  4485.      
  4486.      VOID Init()
  4487.      {
  4488.          InitArea(&AreaInfo,AreaBuffer,5);
  4489.                      /* Always 4 (+1) coordinates */
  4490.          
  4491.          if ((Pointer = (long *)AllocRaster(WIDTH, HEIGHT/2)) == 0)
  4492.          
  4493.              CloseIt("No free space !!");
  4494.                              /* memory for TmpRas */
  4495.          
  4496.          RastPort->AreaInfo = &AreaInfo;
  4497.          RastPort->TmpRas = (struct TmpRas *)
  4498.              InitTmpRas(&TmpRas,Pointer,RASSIZE(WIDTH,HEIGHT/2);
  4499.      }
  4500.      
  4501.      /****************************************************************/
  4502.      /* This routine calculates the new position for the rotation    */
  4503.      /* object.                                                      */
  4504.      /*--------------------------------------------------------------*/
  4505.      /* Entry Parameters : AngleX, AngleY, AngleZ determine          */
  4506.      /*                    the new object position.                  */
  4507.      /*                    rot  - Number of rotations.               */
  4508.      /*                    ko   - Number of line per rotation line.  */
  4509.      /*--------------------------------------------------------------*/
  4510.      /* Returned Values  : None.                                     */
  4511.      /****************************************************************/
  4512.      
  4513.      VOID Rot(AngleX, AngleY, AngleZ, rot, ko)
  4514.      long AngleX, AngleY, AngleZ, rot, ko;
  4515.      {
  4516.          long sx, cx, sy, cy, sz, cz;
  4517.          long i,j;
  4518.          long hx, hy, hz;
  4519.          
  4520.          Move (RastPort,0,RastPort->TxBaseline);
  4521.          Text (RastPort,"Calculating new position....",25);
  4522.      
  4523.                              PAGE 369
  4524.      
  4525. ----------------------------------------------------------------------------
  4526.         
  4527.         sx=sin(AnlgeX);        /* Calculate sin(x,y,z) and         */
  4528.         cx=cos(AngleX);        /* cos(x,y,z) only once             */
  4529.         sy=sin(AngleY);
  4530.         cy=cos(AnlgeY);
  4531.         sz=sin(AngleZ);
  4532.         cz=cos(AnlgeZ);
  4533.             
  4534.         for (i=0; i<rot; i++) /* Calculate global rotation */
  4535.             for(j=0; j<ko; j++)
  4536.               {
  4537.                 hy = Mother[i][j][1] * cx/16384-Mother[i][j][2]*sx/16384;
  4538.                 hz = Mother[i][j][1] * sx/16384+Mother[i][j][2]*cx/16384;
  4539.                 Pixel[i][j][0] = Mother[i][j][0];
  4540.                 Pixel[i][j][1] = hy;
  4541.                 Pixel[i][j][2] = hz;
  4542.             
  4543.                 hx = Pixel[i][j][0]*cy/16384+Pixel[i][j][2]*sy/16384;
  4544.                 hz =-Pixel[i][j][0]*sy/16384+Pixel[i][j][2]*cy/16384;
  4545.                 Pixel[i][j][0] = hx;
  4546.                 Pixel[i][j][2] = hz+bbpz;
  4547.                     
  4548.                 hx=Pixel[i][j][0] *cz/16384-Pixel[i][j][1]*sz/16384;
  4549.                 hy=Pixel[i][j][0] *sz/16384+Pixel[i][j][1]*cz/16384;
  4550.                 Pixel[i][j][0] = hx+bbpx;
  4551.                 Pixel[i][j][1] = hy+bbpy;
  4552.               }
  4553.             Move(RastPort,0,RastPort->TxBaseline);
  4554.             Text(RastPort,"                         ",25);
  4555.         }
  4556.         
  4557.         
  4558.         /********************************************************/
  4559.         /* This function gets the Sine Value from the table.    */
  4560.         /*------------------------------------------------------*/
  4561.         /* Entry Parameters : x for sin(x).                     */
  4562.         /*------------------------------------------------------*/
  4563.         /* Returned Value   : sin(x) * 16384                    */
  4564.         /********************************************************/
  4565.         
  4566.         long sincos(x)
  4567.         long x;
  4568.         {
  4569.             long factor = 1;
  4570.             
  4571.             x %= 360;
  4572.             if (x>180)        /* x > 180 degrees  */
  4573.               {
  4574.                 x -=180;
  4575.                 factor = -1;
  4576.               }
  4577.             
  4578.                                 PAGE 370
  4579.         
  4580. ---------------------------------------------------------------------------
  4581.         
  4582.             if (x>90) x = 180 - x;
  4583.             return(sintab[x]*factor);
  4584.         }
  4585.             
  4586.         /********************************************************/
  4587.         /* This function calculates the Sine for x              */
  4588.         /*------------------------------------------------------*/
  4589.         /* Entry PArameter : x                                  */
  4590.         /*------------------------------------------------------*/
  4591.         /* Returned Value  : sin(x) * 16384                     */
  4592.         /********************************************************/
  4593.         
  4594.         long sin(x)
  4595.         long x;
  4596.         {
  4597.             return(sincos(x));
  4598.         }
  4599.         
  4600.         /*********************************************************/
  4601.         /* This function calculates the Cosine for x.            */
  4602.         /*-------------------------------------------------------*/
  4603.         /* Entry PArameter : x                                   */
  4604.         /*-------------------------------------------------------*/
  4605.         /* Returned Value  : cos(x) * 16384                      */
  4606.         /*********************************************************/
  4607.         
  4608.         long cos(x)
  4609.         long x;
  4610.         {
  4611.             return (sincos(x+90));        /* cos(x) = sin (90+x) */
  4612.         }
  4613.         
  4614.         /********************************************************/
  4615.         /* This function allows the input for the outlines      */
  4616.         /*------------------------------------------------------*/
  4617.         /* Entry Parameters : rot - How many rotations are      */
  4618.         /*                          allowed.                    */
  4619.         /*------------------------------------------------------*/
  4620.         /* Returned Values  : Number of entered Coordinates.    */
  4621.         /********************************************************/
  4622.         
  4623.         long EnterCoords(rot)
  4624.         long rot;
  4625.         {
  4626.             long Class,                    /* For specifying the */
  4627.                  Code;                     /* Intuition Messages.*/
  4628.         
  4629.             long Position;              /* Position where the coordinates */
  4630.             long x,y;                   /* are stored in memory.          */
  4631.         
  4632.             long oldkoorx,oldkoory,oldx,oldy;
  4633.             
  4634.             long Ende = FALSE;          /* Entry Complete ? */
  4635.             
  4636.             ModifyIDCMP(Window, MOUSEMOVE | MOUSEBUTTONS | RAWKEY );
  4637.         
  4638.                                 PAGE 371
  4639.         
  4640. ---------------------------------------------------------------------------
  4641.         
  4642.                                     /* Entry only requires   */
  4643.                                     /* Mouse and Keyboard    */
  4644.             SetRast(RastPort,0);        /* Erase bitmap */
  4645.         
  4646.             SetAPen(RastPort,9);        /* APen, BPen and DrawMode */
  4647.             SetBPen(RastPort,0);        /* setup.                  */
  4648.             
  4649.             SetDrMd(RastPort,JAM2);
  4650.             
  4651.             Position = 0;               /* Where are Coordinates stored ? */
  4652.             
  4653.             Move(RastPort,WIDTH/2,0);        /* Axis intersections */
  4654.             Draw(RastPort,WIDTH/2,HEIGHT);
  4655.             
  4656.             Move(RastPort,0,HEIGHT/2);
  4657.             Draw(RastPort,WIDTH,HEIGHT/2);
  4658.             
  4659.             x=Screen->MouseX;        /* Actual mouse position for o/p */
  4660.             y=Screen->MouseY;
  4661.             
  4662.             while (!Ende && (Position < MAXCOORDS))
  4663.               {
  4664.                 if (1 << Window->UserPort->mp_SigBit)
  4665.                         /* Any messages from Intuition ? */
  4666.             
  4667.                 while (Message = (struct IntuiMessage *)
  4668.                     GetMsg(Window->UserPort))        /* YES */
  4669.                   {
  4670.                     Class = Message->Class;        /* Get required */
  4671.                     Code = Message->Code;          /* Data         */
  4672.                     x = Message->MouseX;
  4673.                     y = Message->MouseY;
  4674.                     ReplyMsg(Message);        /* Have found */
  4675.                                               /* Message !  */
  4676.             
  4677.                     if(Position == 0)
  4678.                       {
  4679.                         oldx = x;
  4680.                         oldy = y;
  4681.                       }
  4682.                 
  4683.                     switch(Class)
  4684.                       {
  4685.                         case MOUSEBUTTONS:
  4686.                             if (Code == SELECTDOWN)
  4687.                               {
  4688.                                 /* Coordinates Relative    */
  4689.                                 /* to axis intersection!   */
  4690.                                 
  4691.                                 if(Position == 0)
  4692.                                   {
  4693.                                     oldkoorx = x;
  4694.                                     oldkoory = y;
  4695.                                   }
  4696.         
  4697.                                 PAGE 372
  4698.         
  4699. ---------------------------------------------------------------------------
  4700.                                 
  4701.                                 CoordArray[Position][0]= x-WIDTH/2;
  4702.                                 CoordArray[Position][1]= HEIGHT/2-y;
  4703.         
  4704.                                 SetDrMd(RastPort,JAM2);
  4705.                                 Move(RastPort,oldkoorx,oldkoory);
  4706.         
  4707.                                 Draw(RastPort,x,y);
  4708.         
  4709.                                 /* Draw small intersection */
  4710.                                 Move(RastPort,x-3,y-3);
  4711.                                 Draw(RastPort,x+3,y+3);
  4712.                                 
  4713.                                 Move(RastPort,x-3,y+3);
  4714.                                 Draw(RastPort,x+3,y-3);
  4715.         
  4716.                                 Move(RastPort,x,y);
  4717.                                     /* Old cursor position */
  4718.                                 
  4719.                                 oldkoorx = x;
  4720.                                 oldkoory = y;
  4721.                                 
  4722.                                 Position++;
  4723.                               }
  4724.                         case MOUSEMOVE:
  4725.         
  4726.                             if (Position > 0)
  4727.                               {
  4728.                                 if ((x != oldx) || (y!=oldy))
  4729.                                   {
  4730.                                     SetDrMd(RastPort, COMPLEMENT | JAM1);
  4731.         
  4732.                                     Move(RastPort,oldkoorx, oldkoory);
  4733.                                     Draw(RastPort,oldx,oldy);
  4734.         
  4735.                                     Move(RastPort,oldkoorx,oldkoory);
  4736.                                     Draw(RastPort,x,y);
  4737.                                         /* Draw line to Actual */
  4738.                                         /* Mouse position      */
  4739.             
  4740.                                     oldx = x;
  4741.                                     oldy = y;
  4742.                                   }
  4743.                               }
  4744.                         break;
  4745.         
  4746.                         case RAWKEY:
  4747.                             if ((Code = 0x50) && (Position > 0))
  4748.                                 Ende = TRUE;
  4749.         
  4750.                                 PAGE 373
  4751.         
  4752. ---------------------------------------------------------------------------
  4753.         
  4754.                                         /* F1 Pressed */
  4755.                         break;
  4756.                     }
  4757.                 }
  4758.             SetDrMd(RastPort,JAM2);
  4759.                         /* Output Mouse position */
  4760.             
  4761.             Move(RastPort,3*WIDTH/4,RastPort->TxBaseline;
  4762.             
  4763.             Text(RastPort,"X: ",3);
  4764.             Text(RastPort,itoa((x-WIDTH/2),4),4);
  4765.             Text(RastPort," Y: ",4);
  4766.             Text(RastPort,itoa(HEIGHT/2-y),4),4);
  4767.           }
  4768.         
  4769.         SetDrMd(RastPort, COMPLEMENT | JAM1);
  4770.         
  4771.         Move(RastPort,oldkoorx,oldkoory);
  4772.         Draw(RastPort,oldx,oldy);
  4773.         
  4774.         SetDrMd(RastPort,JAM2);
  4775.         Rotate(rot,Position);        /* Calculate rotation objects */
  4776.         return(Position);
  4777.         }
  4778.         
  4779.         
  4780.         /********************************************************/
  4781.         /* This routine allows the User to control the Rotation */
  4782.         /* Object.                                              */
  4783.         /*------------------------------------------------------*/
  4784.         /* Entry Parameters : rot = number of rotation lines.   */
  4785.         /*                    ko  = number of pixels per        */
  4786.         /*                          rotation line.              */
  4787.         /*------------------------------------------------------*/
  4788.         /* Returned Value   : none                              */
  4789.         /********************************************************/
  4790.         
  4791.         VOID make_menu(rot,ko)
  4792.         long rot,ko;
  4793.         {
  4794.             long Ende = FALSE;                   /* Program end ? */
  4795.             long First= TRUE;                /* First time shading ? */
  4796.             long Class,Code;                 /* Intuition's messages */
  4797.             long x,y;
  4798.             
  4799.             IDCMPon();                        /* Message Please ! */
  4800.             while (!Ende)
  4801.               {
  4802.                 Wait(1 << Window->UserPort->mp_SigBit);
  4803.                                               /* Answered ? */
  4804.                 while (Message = (struct IntuiMessage *)
  4805.                         GetMsg(Window->UserPort))        /* YES */
  4806.                   {
  4807.                                 PAGE 374
  4808.         
  4809. ----------------------------------------------------------------------------
  4810.         
  4811.                     Class= Message->Class;
  4812.                     Code = Message->Code;
  4813.                     ReplyMsg(Message);
  4814.                         /* We have received it, Thanks */
  4815.             
  4816.                     switch (class)
  4817.                       {
  4818.                         case RAWKEY:
  4819.                             x=y=0;
  4820.                             switch (code)
  4821.                               {
  4822.                                 case 0x4c:        /* Arrow Keys */
  4823.                                     y = -1;
  4824.                                 break;
  4825.                                 case 0x4d:
  4826.                                     y = 1;
  4827.                                 break;
  4828.                                 case 0x4f:
  4829.                                     x=-1;
  4830.                                 break;
  4831.                                 case 0x4e:
  4832.                                     x=1;
  4833.                                 break;
  4834.                               }
  4835.         
  4836.                             if ((x==0) && (y==0)) Status = TRUE;
  4837.                             else
  4838.                             {
  4839.                                 IDCMPoff();        /* No intuition */
  4840.                                 if ((y == -1) && (AngleX == 0))
  4841.                                     AngleX=360;
  4842.                                 if ((x == -1) && (AngleZ == 0))
  4843.                                     AngleZ=360;
  4844.                                 AngleX += y*INCREMENT;
  4845.                                 AngleZ += x*INCREMENT;
  4846.                                 Rot(AngleX, AngleY, AngleZ, rot, ko);
  4847.                                 Show(rot,ko);
  4848.                                 IDCMPon();
  4849.                                 First = TRUE;
  4850.                                 Status = FALSE;
  4851.                             }
  4852.                     break;
  4853.         
  4854.                     case MENUPICK:
  4855.                         if (Code!=MENUNULL)
  4856.                             switch(MENUNUM(Code))
  4857.                               {
  4858.                                 case 0:
  4859.                                     switch(ITEMNUM (Code))
  4860.                                       {
  4861.         /* Shading */                   case 0:
  4862.                                             IDCMPoff();
  4863.                                             if ((First) || (!Status))
  4864.                                                Shade(rot,ko,1,FALSE);
  4865.                                             else
  4866.                                                Shade(rot,ko,1,TRUE);
  4867.         
  4868.                                 PAGE 375
  4869.         
  4870. ---------------------------------------------------------------------------
  4871.         
  4872.                                             First = FALSE;
  4873.                                             Status = TRUE;
  4874.                                             IDCMPon();
  4875.                                         break;
  4876.         
  4877.         /* Hide it */                   case 1:
  4878.                                             IDCMPoff();
  4879.                                             if((First) || (Status))
  4880.                                                 Shade(rot,ko,0,FALSE);
  4881.                                             else
  4882.                                                 Shade(rot,ko,0,TRUE);
  4883.                                         
  4884.                                             First = FALSE;
  4885.                                             Status = TRUE;
  4886.                                             IDCMPon();
  4887.                                         break;
  4888.         
  4889.         /* New coordinates */           case 2:
  4890.                                            IDCMPoff();
  4891.                                            ko = EnterCoords(MAXROTS);
  4892.                                            AngleX = 0;
  4893.                                            AngleZ=  0;
  4894.                                                 /* AngleY = 0 */
  4895.         
  4896.                                            Show(rot,ko);
  4897.                                            First = TRUE;
  4898.                                            Status = FALSE;
  4899.                                            IDCMPon();
  4900.                                         break;
  4901.         
  4902.         /* HardCopy */                  case 3:
  4903.                                             IDCMPoff();
  4904.                                             hardcopy();
  4905.                                             IDCMPon();
  4906.                                         break;
  4907.         
  4908.         /* Quit */                      case 4:
  4909.                                             Ende = TRUE;
  4910.                                         break;
  4911.                                     }
  4912.                                 }
  4913.                             }
  4914.                         }
  4915.                 }
  4916.         }
  4917.         
  4918.                                 PAGE 376
  4919.         
  4920. ---------------------------------------------------------------------------
  4921.         
  4922.         /********************************************************/
  4923.         /* Here is where the HardCopy routines start! Both of    */
  4924.         /* the following functions are used for 'DumpRastPort'  */
  4925.         /* (External Input / Output )                           */
  4926.         /*-------------------------------------------------------*/
  4927.         
  4928.         struct IORequest *CreateExtIO(ioReplyPort,size)
  4929.         struct MsgPort, *ioReplyPort;
  4930.         long size;
  4931.         
  4932.         struct IORequest *ioreq;
  4933.         
  4934.         if (ioReplyPort == NULL) return (NULL);
  4935.         oiReq = (struct IORequest *) AllocMem(size,MEMF_CLEAR);
  4936.         
  4937.         if(ioReq == NULL) return (NULL);
  4938.         ioReq->io_Message.mn_Node.ln_Type = NT_MESSAGE;
  4939.         ioReq->io_Message.mn_Length = size;
  4940.         ioReq->io_Message.mn_ReplyPort = ioReplyPort;
  4941.         return(ioReq);
  4942.         }
  4943.         
  4944.         VOID DeleteExtIO(ioExt)
  4945.         struct IORequest *ioExt;
  4946.         {
  4947.             if(ioExt)
  4948.               {
  4949.                 ioExt->io_Message.mn_Node.ln_Type = 0xff;
  4950.                 ioExt->io_Device = (struct Device *)-1;
  4951.                 ioExt->io_Unit = (struct Unit *)-1;
  4952.                 FreeMem(ioExt, ioExt->io_Message.mn_Length);
  4953.               }
  4954.         }
  4955.         
  4956.         /************************************************/
  4957.         / Here are the actual hardcopy routines.        */
  4958.         /************************************************/
  4959.         
  4960.         VOID hardcopy()
  4961.         
  4962.         union printerIO
  4963.             {
  4964.                 struct IOStdReq ios;
  4965.                 struct IODRPReq iodrp;
  4966.                 struct IOPrtCmdReq iope;
  4967.             };
  4968.         
  4969.         union printerIO *request;
  4970.         struct MsgPort *printerPort;
  4971.         
  4972.             printerPort = CreatePort("printer.port",0);
  4973.             request = (union printerIO *)CreateExtIO(printerport,
  4974.                        sizeof(union,printerIO));
  4975.             
  4976.             if (OpenDevice("printer.device",0,request,0) != 0)
  4977.               {
  4978.                 DeleteExtIO(request);        /* Open Printer. */
  4979.                 DeletePort(printerPort);
  4980.                 CloseIt("Sorry, no Printer !! ");
  4981.               }
  4982.  
  4983.                 PAGE 377
  4984.  
  4985. --------------------------------------------------------------------------
  4986.        
  4987.             request->iodrp.io_Command = PRD_DUMPRPORT;
  4988.                                         /* Dump RastPort command */
  4989.         
  4990.             request->iodrp.io_RastPort = RastPort;
  4991.                                         /* Which RastPort ? */
  4992.         
  4993.             SetRGB4(&Screen-ViewPort,0,15,15,15);
  4994.                                         /* Background color = white */
  4995.         
  4996.             request->iodrp.io_ColorMap = Screen->ViewPort.ColorMap;
  4997.                                         /* For shading on the printer */
  4998.         
  4999.             request->iodrp.io_Modes = NewScreen.ViewModes;
  5000.                                         /* Which Viewmode ? */
  5001.         
  5002.             request->iodrp.io_ScrX = 0;  /* Upper left corner */
  5003.             request->iodrp.io_ScrY = 0;
  5004.             request->iodrp.io_ScrWidth = WIDTH;
  5005.             request->iodrp.io_ScrHeight = HEIGHT;
  5006.                                          /* Lower right */
  5007.                                          /* Corner      */
  5008.             request->iodrp.io_DestCols = 0;
  5009.             request->iodrp.io_DestRows = 0;
  5010.             request->iodrp.io_Special = 0x004;        /* Flag */
  5011.         
  5012.             DoIO(request);                /* printing */
  5013.         
  5014.             CloseDevice(request);
  5015.             DeleteExtIO(request);        /* Close everything */
  5016.             DeletePort(printerPort);
  5017.             SetRGB4(&Screen->ViewPort,0,0,0,0);
  5018.                                         /* Background back to normal */
  5019.         }
  5020.             
  5021.         /****************************************************************/
  5022.         /* here is the MAIN PROGRAM :                                   */
  5023.         /****************************************************************/
  5024.         
  5025.         main()
  5026.         {
  5027.             long Coords;
  5028.             
  5029.             OpenLibs;                /* Open libraries */
  5030.             
  5031.             Coords = EnterCoords(MAXROTS);        /* GET OUTLINE */
  5032.             show(MAXROTS,Coords);                 /* Draw Object */
  5033.             
  5034.             make_menu(MAXROTS,Coords);               /* Menu */
  5035.             
  5036.             CloseIt("Bye Bye");
  5037.             return(0);
  5038.         }
  5039.         
  5040.                                 PAGE 378
  5041.         
  5042. ---------------------------------------------------------------------------
  5043.         
  5044. THE PROGRAM:
  5045. ------------
  5046.         
  5047. After the program starts you can use the mouse to enter the outline of your
  5048. object. When you finish setting all the pixels that design your object, 
  5049. press the <F1> key to see the three dimensional object on the screen. The 
  5050. object will automatically be generated without using the <F1> key if you
  5051. have reached the value of MAXCOORDS that is alowed.
  5052.         
  5053. You can now use the cursor keys to rotate your object.
  5054.         
  5055. You can do much more with the object you just created. To display the 
  5056. object with a shaded grey scale, select the menu item Shading.
  5057.         
  5058. We create the shading effect with a simple algorithm. First we calculate an
  5059. area list that contains the coordinates of all the filled area's corner 
  5060. points. We then sort these points by their middle Z coordinate. After this,
  5061. we first draw the areas that are furthest away from the viewer (naturally
  5062. using Area... functions).
  5063.         
  5064. We use an incrementing counter that changes the shading colour after 
  5065. drawing a specified number of areas.
  5066.         
  5067. The way the menu item 'Hide it' functions is similar to the shading 
  5068. functions. Instead of shading the areas, it makes the area colours equal
  5069. to the background color and therefore hides them. The framing color in OPen
  5070. displays the object and 'Hide it' simulates a hidden line algorithm.
  5071.         
  5072. When you get tired of your current rotation object you can select 
  5073. Coordinates from the menu and make a new object.
  5074.         
  5075. The menu items Hardcopy and Quit are self-explanatory.
  5076.         
  5077. Please make sure that the routines for calculating the rotation object are
  5078. kept together. Also, you can create you own objects (not just rotation 
  5079. objects) by providing the three dimensional coordinates yourself. With
  5080. a slightly modified show routine and help from Rot, you can create and 
  5081. display your own rotation objects.
  5082.         
  5083.                                 PAGE 379
  5084.         
  5085. ---------------------------------------------------------------------------  
  5086.                 > Now load part 5 <
  5087. ---------------------------------------------------------------------------  
  5088.  
  5089.